亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 開發 > JS > 正文

4 種滾動吸頂實現方式的比較

2024-05-06 16:49:43
字體:
來源:轉載
供稿:網友

前言

我入職第二家公司接到的第一個需求就是修復之前外包做的滾動吸頂效果。我當時很納悶為何一個滾動吸頂會有 bug,后來我查看代碼才發現直接用的是 offsetTop 這個屬性,而且并沒有做兼容性處理。

offsetTop

用于獲得當前元素到定位父級( element.offsetParent )頂部的距離(偏移值)。

定位父級 offsetParent 的定義是:與當前元素最近的 position != static 的父級元素。

或許寫這個代碼的人沒有注意到“定位父級”這個這個附屬條件。
后來在項目中總會遇到滾動吸頂的效果需要實現,現在我將我知道的 4 種滾動吸頂實現方式做詳細介紹。

目錄

  1. 使用 position:sticky 實現
  2. 使用 JQuery 的 offset().top 實現
  3. 使用原生的 offsetTop 實現
  4. 使用 obj.getBoundingClientRect().top 實現

望給個 star 支持一下。

四種實現方式

我們先看一下效果圖:

滾動,吸頂

一、使用 position:sticky 實現

1、粘性定位是什么?

粘性定位 sticky 相當于相對定位 relative 和固定定位 fixed 的結合;在頁面元素滾動過程中,某個元素距離其父元素的距離達到 sticky 粘性定位的要求時;元素的相對定位 relative 效果變成固定定位 fixed 的效果。

MDN 傳送門

2、如何使用?

使用條件:

父元素不能 overflow:hidden 或者 overflow:auto 屬性
必須指定 top、bottom、left、right 4 個值之一,否則只會處于相對定位
父元素的高度不能低于 sticky 元素的高度
sticky 元素僅在其父元素內生效

在需要滾動吸頂的元素加上以下樣式便可以實現這個效果:

.sticky {  position: -webkit-sticky;  position: sticky;  top: 0;}

 3、這個屬性好用嗎?

我們先看下在 Can I use 中看看這個屬性的兼容性:

滾動,吸頂

可以看出這個屬性的兼容性并不是很好,因為這個 API 還只是實驗性的屬性。不過這個 API 在 IOS 系統的兼容性還是比較好的。
所以我們在生產環境如果使用這個 API 的時候一般會和下面的幾種方式結合使用。

二、使用 JQuery 的 offset().top 實現

我們知道 JQuery 中封裝了操作 DOM 和讀取 DOM 計算屬性的 API,基于 offset().top 這個 API 和 scrollTop() 的結合,我們也可以實現滾動吸頂效果。

...window.addEventListener('scroll', self.handleScrollOne);...handleScrollOne: function() {  let self = this;  let scrollTop = $('html').scrollTop();  let offsetTop = $('.title_box').offset().top;  self.titleFixed = scrollTop > offsetTop;}...

這樣實現固然可以,不過由于 JQuery 慢慢的退出歷史的舞臺,我們在代碼中盡量不使用 JQuery 的 API。我們可以基于 offset().top 的源碼自己處理原生 offsetTop。于是乎就有了第三種方式。

scrolloTop() 有兼容性問題,在微信瀏覽器、IE、某些 firefox 版本中 $('html').scrollTop() 的值會為 0,于是乎也就有了第三種方案的兼容性寫法。

三、使用原生的 offsetTop 實現

我們知道 offsetTop 是相對定位父級的偏移量,倘若需要滾動吸頂的元素出現定位父級元素,那么 offsetTop 獲取的就不是元素距離頁面頂部的距離。

我們可以自己對 offsetTop 做以下處理:

getOffset: function(obj,direction){  let offsetL = 0;  let offsetT = 0;  while( obj!== window.document.body && obj !== null ){    offsetL += obj.offsetLeft;    offsetT += obj.offsetTop;    obj = obj.offsetParent;  }  if(direction === 'left'){    return offsetL;  }else {    return offsetT;  }}

使用:

...window.addEventListener('scroll', self.handleScrollTwo);...handleScrollTwo: function() {  let self = this;  let scrollTop = window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop;  let offsetTop = self.getOffset(self.$refs.pride_tab_fixed);  self.titleFixed = scrollTop > offsetTop;}...

你是不是看出了以上兩種方式的一些問題?

我們一定需要使用 scrollTop - offsetTop 的值來實現滾動吸頂的效果嗎?答案是否定的。

我們一同看看第四種方案。

四、使用 obj.getBoundingClientRect().top 實現

定義:
這個 API 可以告訴你頁面中某個元素相對瀏覽器視窗上下左右的距離。
使用:
tab 吸頂可以使用 obj.getBoundingClientRect().top 代替 scrollTop - offsetTop,代碼如下:

// html<div class="pride_tab_fixed" ref="pride_tab_fixed">  <div class="pride_tab" :class="titleFixed == true ? 'isFixed' :''">    // some code  </div></div>// vueexport default {  data(){   return{    titleFixed: false   }  },  activated(){   this.titleFixed = false;   window.addEventListener('scroll', this.handleScroll);  },  methods: {   //滾動監聽,頭部固定   handleScroll: function () {    let offsetTop = this.$refs.pride_tab_fixed.getBoundingClientRect().top;    this.titleFixed = offsetTop < 0;    // some code   }  } }

offsetTop 和 getBoundingClientRect() 區別

1. getBoundingClientRect():

用于獲得頁面中某個元素的左,上,右和下分別相對瀏覽器視窗的位置。不包含文檔卷起來的部分。
該函數返回一個 object 對象,有6個屬性:
top, right, buttom, left, width, height。
(在 IE 中,默認坐標從(2,2)開始計算,只返回 top,lef,right,bottom 四個值)

2. offsetTop:

用于獲得當前元素到定位父級( element.offsetParent )頂部的距離(偏移值)。

定位父級 offsetParent 的定義是:與當前元素最近的 position != static 的父級元素。

offsetTop 和 offsetParent 方法相結合可以獲得該元素到 body 上邊距的距離。代碼如下:

getOffset: function(obj,direction){  let offsetL = 0;  let offsetT = 0;  while( obj!== window.document.body && obj !== null ){    offsetL += obj.offsetLeft;    offsetT += obj.offsetTop;    obj = obj.offsetParent;  }  if(direction === 'left'){    return offsetL;  }else {    return offsetT;  }}

延伸知識點

offsetWidth:

元素在水平方向上占用的空間大?。?br /> offsetWidth =  border-left + padding-left + width + padding-right + border-right

offsetHeight:

元素在垂直方向上占用的空間大?。?br /> offsetHeight =  border-top + padding-top + height + padding-bottom + border-bottom

注:如果存在垂直滾動條,offsetWidth 也包括垂直滾動條的寬度;如果存在水平滾動條,offsetHeight 也包括水平滾動條的高度;

offsetTop:

元素的上外邊框至 offsetParent 元素的上內邊框之間的像素距離;

offsetLeft:

元素的左外邊框至 offsetParent 元素的左內邊框之間的像素距離;

注意事項

  1. 所有偏移量屬性都是只讀的;
  2. 如果給元素設置了 display:none,則它的偏移量屬性都為 0;
  3. 每次訪問偏移量屬性都需要重新計算(保存變量);
  4. 在使用的時候可能出現 DOM 沒有初始化,就讀取了該屬性,這個時候會返回 0;對于這個問題我們需要等到 DOM 元素初始化完成后再執行。

遇到的兩個問題

一、吸頂的那一刻伴隨抖動

出現抖動的原因是因為:在吸頂元素 position 變為 fixed 的時候,該元素就脫離了文檔流,下一個元素就進行了補位。就是這個補位操作造成了抖動。

解決方案
為這個吸頂元素添加一個等高的父元素,我們監聽這個父元素的 getBoundingClientRect().top 值來實現吸頂效果,即:

<div class="title_box" ref="pride_tab_fixed">  <div class="title" :class="titleFixed == true ? 'isFixed' :''">  使用 `obj.getBoundingClientRect().top` 實現  </div></div>

這個方案就可以解決抖動的 Bug 了。

二、吸頂效果不能及時響應

這個問題是我比較頭痛,之前我沒有在意過這個問題。直到有一天我用美團點外賣的時候,我才開始注意這個問題。
描述:

當頁面往下滾動時,吸頂元素需要等頁面滾動停止之后才會出現吸頂效果
當頁面往上滾動時,滾動到吸頂元素恢復文檔流位置時吸頂元素不恢復原樣,而等頁面停止滾動之后才會恢復原樣

原因:

在 ios 系統上不能實時監聽 scroll 滾動監聽事件,在滾動停止時才觸發其相關的事件。
解決方案:
還記得第一種方案中的 position:sticky 嗎?這個屬性在 IOS6 以上的系統中有良好的兼容性,所以我們可以區分 IOS 和 Android 設備做兩種處理。

IOS 使用 position:sticky,Android 使用滾動監聽 getBoundingClientRect().top 的值。

如果 IOS 版本過低呢?這里提供一種思路:window.requestAnimationFrame()。

以上所述是小編給大家介紹的4種滾動吸頂實現方式的比較詳解整合,希望對大家有所幫助,如果大家有任何疑問請給我留言,小編會及時回復大家的。在此也非常感謝大家對VeVb武林網網站的支持!


注:相關教程知識閱讀請移步到JavaScript/Ajax教程頻道。
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
亚洲欧美成人精品| 久久这里只有精品视频首页| 在线亚洲午夜片av大片| 最好看的2019的中文字幕视频| 最近更新的2019中文字幕| 欧美一级片在线播放| 久久99热精品这里久久精品| 国产亚洲一区二区在线| 午夜精品久久久99热福利| 欧美亚洲在线观看| 国产欧美精品一区二区三区-老狼| 丝袜亚洲另类欧美重口| 亚洲性夜色噜噜噜7777| 成人av在线网址| 精品久久在线播放| 色哟哟亚洲精品一区二区| 国产精品h在线观看| 欧美性猛交xxxxx免费看| 深夜福利日韩在线看| 国产精品久久久久久久久久新婚| 欧美亚洲在线视频| 91国语精品自产拍在线观看性色| 综合av色偷偷网| 国产大片精品免费永久看nba| 97超级碰碰碰久久久| 日韩av网址在线观看| 久久成人精品电影| 国产日韩精品综合网站| 亚洲男人av在线| 欧美精品日韩三级| 欧美猛交免费看| 欧美精品一区二区三区国产精品| 国产一区二区在线免费视频| 黄色一区二区在线观看| 亚洲国产小视频在线观看| 91在线高清免费观看| 91精品国产91久久久久久吃药| 久久久99久久精品女同性| 国产69久久精品成人| 亚洲图中文字幕| 91成人性视频| 色老头一区二区三区在线观看| 欧美亚洲午夜视频在线观看| 中文在线资源观看视频网站免费不卡| 在线视频欧美性高潮| 性欧美长视频免费观看不卡| 亚洲网站在线播放| 欧美大尺度电影在线观看| 日韩欧美国产高清91| 在线成人激情黄色| 国产一区二区三区在线观看视频| 伊人久久久久久久久久| 国产一区红桃视频| 精品久久国产精品| 国产精品久久久久久一区二区| 国产精品入口夜色视频大尺度| 久久影视三级福利片| 日韩中文字幕免费视频| 欧美激情一二三| 欧美成人午夜视频| 国产精品稀缺呦系列在线| 国产精品久久久久久久9999| 亚洲一区二区中文| 91av在线视频观看| 色老头一区二区三区在线观看| 在线视频一区二区| 亚洲电影免费观看高清完整版在线| 国产欧美一区二区| 国产成人av网址| 91影视免费在线观看| 91沈先生作品| 精品国产乱码久久久久久婷婷| 日日噜噜噜夜夜爽亚洲精品| 久久久国产一区二区| 亚洲成人久久一区| 日韩欧美在线网址| 久久久久久久999精品视频| 亚洲精品自在久久| 久久免费视频这里只有精品| 欧美视频第一页| 亚洲a一级视频| 欧美日韩美女在线观看| 亚洲欧美国产精品专区久久| 韩日欧美一区二区| 亚洲欧美一区二区精品久久久| 久久福利视频网| 欧美视频在线看| 欧美高清videos高潮hd| 中文字幕国产精品| 操日韩av在线电影| 欧美日韩精品在线观看| 日韩理论片久久| 国产精品大片wwwwww| 国产亚洲欧美视频| 国产欧美一区二区白浆黑人| 亚洲精品aⅴ中文字幕乱码| 91精品视频免费| 国产免费成人av| 热久久美女精品天天吊色| 色偷偷噜噜噜亚洲男人的天堂| 久久久久亚洲精品| 亚洲欧洲在线播放| 麻豆国产精品va在线观看不卡| 国产精品高潮呻吟久久av无限| 欧美视频在线免费| 亚洲伦理中文字幕| 欧美人与物videos| 91超碰caoporn97人人| 欧美高清第一页| 国产精品久久久久免费a∨| 欧美激情xxxx| 久久精品91久久久久久再现| 欧美—级高清免费播放| 亚洲最大福利网站| 国产欧美在线看| 亚洲女同性videos| www.日本久久久久com.| 国产精品久久视频| 国模精品视频一区二区| 超碰精品一区二区三区乱码| 亚洲国产精品国自产拍av秋霞| 一区二区三区亚洲| 欧美性极品少妇精品网站| 黑人巨大精品欧美一区二区免费| 日韩在线视频国产| 欧美日本高清一区| 欧美又大又硬又粗bbbbb| 国产成人精品一区| 国产精品自拍小视频| 成人综合网网址| 国产成人jvid在线播放| 精品国产老师黑色丝袜高跟鞋| 中文字幕日韩欧美在线视频| 97超级碰碰人国产在线观看| 91色视频在线观看| 国产精品久久久久91| 亚洲午夜国产成人av电影男同| 国产精品扒开腿做爽爽爽男男| 操91在线视频| 在线观看日韩av| 久久久久久久网站| 不卡伊人av在线播放| 亚洲精品自拍视频| 精品国产区一区二区三区在线观看| 一区二区三区 在线观看视| 国语自产精品视频在线看一大j8| 欧美一级片久久久久久久| 91在线视频精品| 九色成人免费视频| 亚洲高清不卡av| 成人福利网站在线观看| 国产大片精品免费永久看nba| 正在播放欧美一区| x99av成人免费| 97色在线播放视频| 亚洲国产精品成人va在线观看| 国产精品美女无圣光视频| 亚洲福利视频久久| 欧美日韩中文字幕在线视频| 亚洲精品91美女久久久久久久| 欧美精品第一页在线播放| 欧美日韩激情网| 欧美午夜视频一区二区| 久久久精品国产亚洲|