JQ的offset().top與js的offsetTop區別詳解

1、前言css

最近在作一個圖片懶加載的插件,就縱軸(Y軸)而言,我須要時時獲取圖片的上偏移量,好判斷是否已進入視圖區域,而我所理解的是offsetTop應該是跟offset().top同樣的,而後陷入了由於不瞭解它們區別,而帶來BUG的死坑。這裏經過實驗整理,作個清晰好懂的筆記,若是你也想弄清,建議複製個人代碼跟着操做,印象會更爲深入。html

2、offset().top與offsetTop什麼意思?它們都是相對誰的上偏移量?面試

offset().top是JQ的方法,須要引入JQ才能使用,它獲取的是你綁定元素上邊框相對於文檔頂端的偏移量,咱們能夠把文檔理解成一幅圖,這幅圖包含了html,html內容越多圖越長,瀏覽網頁時,就是透過透明的玻璃(s視窗)在看這幅畫。佈局

offsetTop是原生JS的方法,它獲取的是你綁定元素上邊框相對離本身最近且position屬性爲非static的祖先元素的偏移量(後面會具體解釋)。spa

區別一:offset().top與offsetTop偏移量參照對象不一樣,offset().top始終是html,而offsetTop參照的對象是可變的。插件

你們能夠先拷貝下面代碼:3d

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地址引入就能夠了。code

在css中我爲ul加了一個上邊距爲200px,先不解決上邊距坍塌的問題,這會致使整個body區域距離頁頭有200px的空白區域,以方便區分body和html,以下圖html範圍和body範圍:htm

這是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也隨着咱們的滾動條往下拉,有了滾動距離,也在慢慢變大。很好理解不是嗎?

3、猜想: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的參照對象這下就不一樣了,咱們滾動滾動條能夠看到規則就不適用了:

4、總結

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獲取元素距離視窗頂部可變距離

轉載請標明出處,謝謝。好睏...........

相關文章
相關標籤/搜索