溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

vue實現吸頂、錨點和滾動高亮按鈕效果

發布時間:2020-10-12 23:53:49 來源:腳本之家 閱讀:705 作者:lemonChen 欄目:web開發

因公司后臺管理系統很多功能技術老舊,最近在用vue重構公司的后臺管理系統,在做商品管理添加商品這一塊,借鑒淘寶的添加商品的交互,需要實現一個簡單的吸頂、錨點和滾動高亮按鈕的效果。

需求

  1. 滾動頁面到頂部,實現某元素固定到頂部效果
  2. 點擊某個按鈕,頁面滾動到相應的位置
  3. 滾動頁面,當到達某個位置時,高亮對應的相關按鈕

元素吸頂實現方式

關于元素吸頂效果,通過查閱相關資料和相關測試,有三種方式(還有一種是jquery的方法,這里就不介紹了)

一、使用position:sticky

1. 什么是position:sticky?

粘性定位元素相當于position:relative和position:sticky的結合體,受限于父級元素,在不同的條件下呈現出不同的頁面效果

2. 如何使用sticky?

sticky元素效果完全受限于父級元素,使用條件:

1.sticky元素的父元素的overflow只能設置為visible,否則會導致沒有粘滯效果

2.sticky元素的父元素不能設置固定的高度,否則會導致沒有粘滯效果

3.sticky滿足條件變成fixed定位時,與標準fixed元素不一樣,不會脫離文檔流

4.sticky 定位的元素不能添加一個只包含自身的父元素,會導致沒有粘滯效果

5.同一個父級元素中的sticky元素,如果定位值相等,則會重疊,如果屬于不同父級元素中,則會擠掉之前的元素,形成依次占位的效果 具體實現效果如下:

.sticky-box{ 
 position: sticky; 
 position: -webkit-sticky;
 top: 60px; //可通過js動態設置
}

3.兼容性

通過查看can i use 可以看到相關的兼容性:


可以看出這個屬性的兼容性不是那么好,如果項目需要兼容到ie11等的話,就不是那么適用了

二、使用offsetTop**

HTMLElement.offsetTop 為只讀屬性,它返回當前元素相對于其 offsetParent 元素的頂部內邊距的距離。因此我們需要注意的是,在監聽頁面滾動的過程中,需要將定位父級元素的偏移量也計算在內,可以如下寫法:

//獲取當前元素的offsetTop
  getOffsetTop(obj) {
   let offsetTop = 0;
   while (obj != window.document.body && obj != null) {
    offsetTop += obj.offsetTop;
    obj = obj.offsetParent;
   }
   return offsetTop;
  }

通過在vue的mounted生命周期函數中添加監聽事件滾動的事件:

mounted() {
  /**通過給變成固定定位的元素添加一個同等高度的父元素,防止該元素變成固定定位時,脫離文檔流導致的頁面抖動 */
  this.tabsHeight = this.$refs.elTabs.offsetHeight;
  window.addEventListener("scroll", this.handleScroll);
 },
 destroyed() {
  //離開該頁面需要移除這個監聽的事件
  window.removeEventListener("scroll", this.handleScroll);
 },
  methods: {
  /**滾動事件 */
  handleScroll() {
    //獲取頁面滾動條的高度
    let scrollTop = window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop;
    let offsetTop = this.getOffsetTop(this.$refs.elTabs);
    this.isFixed = scrollTop > offsetTop;
  }
 }

同時如果這種吸頂方式在項目中會多次用到,就可以封裝成組件的形式

三、使用getBoundingClientRect().top**

還有一種更為直接的方式,可以實現吸頂效果,就是使用getBoundingClientRect().top來獲取元素相對于視口(瀏覽器窗口)的位置,相對于offsetTop,該方法不用考慮到吸頂元素的父級元素和頁面滾動條的高度,直接對該元素進行處理即可,實現如下: /* 滾動事件 / handleScroll() { / * getBoundingClientRect().top 獲取某元素距離瀏覽器頂部的高度,不包含滾動的距離 */ let tabOffsetTop = this.$refs.stickyBox.getBoundingClientRect().top; this.isFixed = tabOffsetTop < this.offsetTop }

/**滾動事件 */
  handleScroll() {
   /**
    * getBoundingClientRect().top 獲取某元素距離瀏覽器頂部的高度,不包含滾動的距離
    this.offsetTop 表示的是吸頂元素距離頂部的條件值(一般項目需求是0)
    */
   let tabOffsetTop = this.$refs.stickyBox.getBoundingClientRect().top;
   this.isFixed = tabOffsetTop < this.offsetTop
  }

錨點定位

點擊相應的按鈕,頁面滾動到相應的位置,目前我知道實現該功能的方式有兩種:

1. 使用a標簽定位 2. 使用js模擬錨點定位

使用a標簽定位

這是一種常見的定位方式,它有兩種實現方式:

1. 通過href屬性鏈接到指定元素的id

2.另一種是添加一個 a 標簽,再將 href 屬性鏈接到這個 a 標簽的 name 屬性

<a href="#view1">按鈕1</a> 
 <a href="#view2">按鈕1</a> 
 <div id="view1">視圖1</div> 
 <div><a name="view2">視圖2</a></div> 

這種定位方式很簡單,支持任意標簽的定位,但是a標簽的定位會改變路由的hash,如果有相關路由會進行路由跳轉

使用js模擬錨點定位

通過js獲取元素的scrollTop值,使其滾動到指定的位置,就能實現錨點定位效果,這里的tab切換選項,用到是的element-ui的el-tabs組件,具體實現如下:

<!-- html -->
 <el-tabs v-model="activeName" type="card" @tab-click="tabClick">
  <el-tab-pane :label="item.name" :name="item.key" v-for="item in tabList" :key="item.key"></el-tab-pane>
</el-tabs>
<!-- js -->
methods:{
 //獲取當前元素的offsetTop
 getOffsetTop(obj) {
  let offsetTop = 0;
  while (obj != window.document.body && obj != null) {
  offsetTop += obj.offsetTop;
  obj = obj.offsetParent;
 }
  return offsetTop;
 },
 <!--錨點點擊事件-->
 <!--fixedHeight 滾動的位置上方固定的高度-->
 tabClick(e) {
  let _this = this;
  //獲取當前選中的index以便后面滾動高亮
  this.index = parseInt(e.index);
  //給定一個標識,錨點事件不觸發滾動
  this.isScroll = false;
  this.isChange = false;
  //獲取當前選中元素的top值(給元素綁定對應的ref值)
  let offsetTop = this.getOffsetTop(this.$refs[this.activeName]);
  let scrollTop = offsetTop - this.fixedHeight;
  window.scrollTo({
    top: scrollTop
  });
}

不得不提的一個方法就是scrollIntoView,Element.scrollIntoView() 方法讓當前的元素滾動到瀏覽器窗口的可視區域內,同時還支持動態效果,但是不支持配置滾動到距離頂部的距離,會出現遮罩現象,但是很適合做會到頂部的功能

滾動高亮按鈕

當用戶滾動內容區時,高亮距離按鈕組件最近的那個元素所對應的按鈕。 通過監聽滾動事件,獲取當前選中的tab的offsetTop值和當前頁面的scrollTop值,判斷向上或者向下滾動,做出不同的處理,具體如下:

//頁面滾動要做的事情
handleScroll() {
  let scrollTop =
    window.pageYOffset ||
    document.documentElement.scrollTop ||
    document.body.scrollTop;
   this.scrollTop = scrollTop;
   <!--isScroll 用于避免錨點事件觸發頁面滾動-->
   if (!this.isScroll) return;
   /**
    * scrollTop 頁面的滾動條的高度
    * offsetTop 當前選中的tab元素的offsetTop
    * offsetHeight 當前選中元素的高度
    */
   let offsetTop = this.getOffsetTop(this.$refs[this.activeName]);
   let offsetHeight = this.$refs[this.activeName].offsetHeight;
   let actuaTop = scrollTop + this.fixedHeight;
   let length = this.tabList.length;
   /**
    * 頁面滾動中根據相應位置變換選中tab
    */
   if (actuaTop < offsetTop && this.index > 0) {
    this.index = this.index - 1;
    this.activeName = this.tabList[this.index].key;
   } else if (this.index < length && actuaTop > offsetTop + offsetHeight) {
    this.index = this.index + 1;
    this.activeName = this.tabList[this.index].key;
 }
}

性能優化

頁面中讀取屬性會導致頁面reflow(下次會對導致頁面reflow和repaint 的操作做一個總結),過度的reflow會導致頁面性能下降,所以我們應該盡量減少reflow的次數,以便給用戶更好的體驗。 如果產品可以接受效果有延遲,就可以使用節流函數控制在一定時間內只執行一次函數(節流函數可以使用lodash.js 封裝好的 throttle 方法)

總結

寫到這里,需求中的三個功能都已經實現,也許還存在更好的方案,但是通過這次實現這三個需求,如果大家有其他更好的方法,歡迎留言補充,但我也從中學習到了一些東西 1.position:sticky的用法和使用條件

2.scrollTop、offsetTop等元素的相關屬性、getBoundingClientRect()用法和 scrollTo、scrollIntoView的用法 3.錨點時間和滾動高亮事件導致的沖突處理等

以上所述是小編給大家介紹的vue實現吸頂、錨點和滾動高亮按鈕效果,希望對大家有所幫助,如果大家有任何疑問請給我留言,小編會及時回復大家的。在此也非常感謝大家對億速云網站的支持!
如果你覺得本文對你有幫助,歡迎轉載,煩請注明出處,謝謝!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

亚洲午夜精品一区二区_中文无码日韩欧免_久久香蕉精品视频_欧美主播一区二区三区美女