JQ的offset().top与js的offsetTop区别详解
一、前言
最近在做一个图片懒加载的插件,就纵轴(Y轴)而言,我需要时时获取图片的上偏移量,好判断是否已进入视图区域,而我所理解的是offsetTop应该是跟offset().top一样的,然后陷入了因为不了解它们区别,而带来BUG的死坑。这里通过实验整理,做个清晰好懂的笔记,如果你也想弄清,建议复制我的代码跟着操作,印象会更为深刻。
二、offset().top与offsetTop什么意思?它们都是相对谁的上偏移量?
offset().top是JQ的方法,需要引入JQ才能使用,它获取的是你绑定元素上边框相对于文档顶端的偏移量,我们可以把文档理解成一幅图,这幅图包含了html,html内容越多图越长,浏览网页时,就是透过透明的玻璃(视窗)在看这幅画。
offsetTop是原生JS的方法,它获取的是你绑定元素上边框相对离自己最近且position属性为非static的祖先元素的偏移量(后面会具体解释)。
区别一:offset().top与offsetTop偏移量参照对象不同,offset().top始终是html,而offsetTop参照的对象是可变的。
大家可以先拷贝下面代码:
html部分
<ul class="contain">
<li><div></div></li>
<li><div></div></li>
<li><div></div></li>
<li><div></div></li>
</ul> css部分
body{
position:relative;
padding:0;
margin:0;
/* display: table; */
}
.contain{
list-style: none;
height: 1000px;
width: 800px;
overflow: auto;
margin-top:200px;
background-color:#ebc38d;
}
.contain>li{
margin-bottom: 10px;
}
.contain>li>div{
background-color: #e4393c;
width: 300px;
height: 400px;
} js部分
var ul = document.querySelector(".contain");
var div = document.querySelectorAll("div")[0];
function demo() {
var top1 = div.offsetTop;//第一个div的上偏移量
var top2 = $(div).offset().top;//第一个div的上偏移量
var top3 =ul.scrollTop;//ul自己的滚动条已滚动的距离,默认是0,往下滚动慢慢变大
console.log(top2, top1, top3);
} demo()
ul.addEventListener("scroll", demo);
html自己生成补全,记得引入JQ,这里提供一个静态资源库,直接复制JQ地址引入就可以了。
在css中我为ul加了一个上边距为200px,先不解决上边距坍塌的问题,这会导致整个body区域距离页头有200px的空白区域,以方便区分body和html,如下图html范围和body范围:
这是html的范围
这是body的范围,很明显比html要矮出200px的空白区域,因为html没有设置上margin,可以说文档和html范围是相同的:
打开控制台,我们可以看到输出了200,0,0;
第一个200:offset().top的值是第一个div上边界相对html的上偏移量,因为有200px的margin,所以是200;
第二个0:offsetTop的值第一个div上边界相对body的上偏移量,因为从div往上找,第一个position属性为非static的(relative,absolute,fixed其一)的祖先元素是body,所以相对body。
第三个0:scrollTop的值容器ul滚动条滚动的距离,因为默认没有滚动,所以是0;
我们来做下改变,将body的position:relative属性移动到html上,其它不变,像这样:
我们可以看到此时输出:200,200,0;
第一个200:offset().top的值还是第一个div相对html的上偏移量,因为margin的问题。
第二个200:offsetTop的值验证了我们之前的概念,offsetTop的参照对象是第一个position不为static的祖先元素,此时被我们修改成了html;
第三个0:容器ul的滚动条距离。
我们将body的display:table的注释去掉,将html的position属性去掉并还给body。其它不变,像这样,毕竟布局中上margin坍塌本来就不合理:
此时的body已经跟html范围相同,不存在200px空白区域,虽然offsetTop参照的是body,offset().top参照的是html,但从两个参照对象的上边界而言,可以理解为参照的是统一对象。
可以看到控制台还是输出200,200,0。
相同点:当无滚动条且offsetTop与offset().top参照对象相同时,它们获取的值相同。
区别二:offsetTop获取的偏移量不随滚动条滚动变化,但offset().top跟这滚动条变化
我们尝试滚动ul的滚动条,观察输出值的变化
可以看到offset().top的值随着滚动条滚动越变越小,因为第一个div的上边界与html的上边界越来越近了。
而offsetTop的值从一开始的200一直就没变化,不受滚动条影响。
而ul的scrollTop也随着我们的滚动条往下拉,有了滚动距离,也在慢慢变大。很好理解不是吗?
三、猜测:offset().top = offsetTop - scrollTop
JQ能拿到变化的上偏移量,原生JS怎么拿这个变化的值呢?参照上面试验,scrollTop变大的同时,offset().top也在随之变小,只有 offsetTop恒定不变。
不用猜测了,大家将滚动输出打印的数字做个计算,很明显,第一个数字 = 第二个数字 - 第三个数字,就算offset().top为负数也一样遵守规则:
那我们可以得出这样一个规律:
当一个元素的offset().top与offsetTop的参照对象相同时,offset().top的值等于offsetTop的值减去scrollTop的值。
我们将body的display属性注释掉,像这样
很明显,因为margin坍塌的问题,body和html之间又多了200px的空白间隔区域,offset().top与offsetTop的参照对象这下就不同了,我们滚动滚动条可以看到规则就不适用了:
四、总结
offsetTop与offset().top相同点:
1.当无滚动条且offsetTop与offset().top参照对象相同时,它们获取的值相同。
offsetTop与offset().top不同点:
1.offset().top与offsetTop偏移量参照对象不同,offset().top始终是文档,而offsetTop参照的对象是可变的。
2.offsetTop获取的偏移量不随滚动条滚动变化,但offset().top随着滚动条变化(注意滚动监听的是一个有滚动条的元素,而不是window)
一个规律:
1.当一个元素的offset().top与offsetTop的参照对象相同时,offset().top = offsetTop - scrollTop
还是建议大家能照着练一遍,要不了多少时间,印象也会更深刻,也欢迎大家的补充和纠正,毕竟我也可能有理解错误的地方。
另外,本文中的例子是元素有滚动条的情况,如果监听的是window的滚动条,这个结论就不适用,不过我们可以利用JS的getBoundingClientRect解决,想知道getBoundingClientRect与offset().top以及offsetTop有何区别吗?欢迎阅读博主另一篇博客:
JQ的offset().top与JS的getBoundingClientRect区别详解,JS获取元素距离视窗顶部可变距离
转载请标明出处,谢谢。好困...........
JQ的offset().top与js的offsetTop区别详解的更多相关文章
- JQ的offset().top与JS的getBoundingClientRect区别详解,JS获取元素距离视窗顶部可变距离
壹 ❀ 引 我在 JQ的offset().top与js的offsetTop区别详解 这篇博客中详细分析了JQ方法offset().top与JS属性offsetTop的区别,并得出了一条offset( ...
- jquery的offset().top和js的offsetTop的区别,以及jquery的offset().top的实现方法
jquery的offset().top和js的offsetTop的区别,以及jquery的offset().top的实现方法 offset().top是JQ的方法,需要引入JQ才能使用,它获取的是你绑 ...
- jquery的offset().top与javascript的offsetTop区别?
offset().top是jquery的方法,需引入jquery,它获取你绑定元素上边框相对于html上边界的偏移量 offsetTop是原生js的方法,它获取你绑定元素上边框相对于离自己最近且pos ...
- js调试工具Console命令详解
这篇文章主要介绍了js调试工具Console命令详解,需要的朋友可以参考下 一.显示信息的命令 复制代码 代码如下: < !DOCTYPE html> < html> &l ...
- 【微信小程序项目实践总结】30分钟从陌生到熟悉 web app 、native app、hybrid app比较 30分钟ES6从陌生到熟悉 【原创】浅谈内存泄露 HTML5 五子棋 - JS/Canvas 游戏 meta 详解,html5 meta 标签日常设置 C#中回滚TransactionScope的使用方法和原理
[微信小程序项目实践总结]30分钟从陌生到熟悉 前言 我们之前对小程序做了基本学习: 1. 微信小程序开发07-列表页面怎么做 2. 微信小程序开发06-一个业务页面的完成 3. 微信小程序开发05- ...
- JS中this关键字详解
本文主要解释在JS里面this关键字的指向问题(在浏览器环境下). 阅读此文章,还需要心平气和的阅读完,相信一定会有所收获,我也会不定期的发布,分享一些文章,共同学习 首先,必须搞清楚在JS里面,函数 ...
- 原生JS:String对象详解
@import url(http://i.cnblogs.com/Load.ashx?type=style&file=SyntaxHighlighter.css);@import url(/c ...
- JS 中 this 关键字详解
本文主要解释在JS里面this关键字的指向问题(在浏览器环境下). 首先,必须搞清楚在JS里面,函数的几种调用方式: 普通函数调用 作为方法来调用 作为构造函数来调用 使用apply/call方法来调 ...
- Js apply() call()使用详解
Js apply方法详解我在一开始看到javascript的函数apply和call时,非常的模糊,看也看不懂,最近在网上看到一些文章对apply方法和call的一些示例,总算是看的有点眉目了,在这里 ...
随机推荐
- 201621123002《JAVA程序设计》第五周学习总结
1. 本周学习总结 1.1 写出你认为本周学习中比较重要的知识点关键词 接口 interface关键字 implements关键字 Comparable abstract Comparator 1.2 ...
- 深入理解JVM(三)垃圾收集器和内存分配策略
3.1 关于垃圾收集和内存分配 垃圾收集和内存分配主要针对的区域是Java虚拟机中的堆和方法区: 3.2 如何判断对象是否“存活”(存活判定算法) 垃圾收集器在回收对象前判断其是否“存活”的两个算法: ...
- 【轻松前端之旅】<a>元素妙用
浏览器读取服务器内容时,通过URL(包含:协议+域名+绝对路径)如:https://www.baidu.com/index.html浏览器从本地读取内容时,会用file协议.如:file:///E:/ ...
- s32 kickstart 批量自动安装系统
1. 自动安装操作系统 http://blog.oldboyedu.com/autoinstall-kickstart/ 自动安装操作系统的解决方案:kickstart.cobbler(披着web ...
- 1.Spring框架入门案例
一.简单入门案例 入门案例:IoC 1.项目创建与结构 2.接口与实现类 User.java接口 package com.jd.ioc; /** * @author weihu * @date 201 ...
- Android开发 - 掌握ConstraintLayout(二)介绍
介绍 发布时间 ConstraintLayout是在2016的Google I/O大会上发布的,经过这么长时间的更新,现在已经非常稳定. 支持Android 2.3(API 9)+ 目前的Androi ...
- 项目Alpha冲刺(团队4/10)
项目Alpha冲刺(团队4/10) 团队名称: 云打印 作业要求: 项目Alpha冲刺(团队) 作业目标: 完成项目Alpha版本 团队队员 队员学号 队员姓名 个人博客地址 备注 221600412 ...
- navicat连接linux系统中mysql-错误:10038
输入 命令 netstat -anp(查看所有的进程和端口使用情况) (注:Local Address一列中: 0.0.0.0 表示监听本地所有ip地址,其他电脑是可以访问的,并且修改ip不受影响. ...
- Linux pwn入门教程——格式化字符串漏洞
本文作者:Tangerine@SAINTSEC 原文来自:https://bbs.ichunqiu.com/thread-42943-1-1.html 0×00 printf函数中的漏洞printf函 ...
- InnoDB体系架构(三)Checkpoint技术
Checkpoint技术 前篇 InnoDB体系架构(二)内存 从缓冲池.缓冲池的管理.重做日志缓冲.额外内存缓冲这四个点介绍了InnoDB存储引擎的内存结构,而在将缓冲池的数据刷新到磁盘的过程中使用 ...