溫馨提示×

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

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

vue如何監(jiān)聽(tīng)滾動(dòng)事件實(shí)現(xiàn)錨點(diǎn)鏈接平滑滾動(dòng)

發(fā)布時(shí)間:2021-07-28 09:17:24 來(lái)源:億速云 閱讀:1209 作者:小新 欄目:web開(kāi)發(fā)

這篇文章將為大家詳細(xì)講解有關(guān)vue如何監(jiān)聽(tīng)滾動(dòng)事件實(shí)現(xiàn)錨點(diǎn)鏈接平滑滾動(dòng),小編覺(jué)得挺實(shí)用的,因此分享給大家做個(gè)參考,希望大家閱讀完這篇文章后可以有所收獲。

基于vue監(jiān)聽(tīng)滾動(dòng)事件,實(shí)現(xiàn)錨點(diǎn)鏈接平滑滾動(dòng)

近日在做一個(gè)vue項(xiàng)目的餐飲模塊,小編需要實(shí)現(xiàn)一個(gè)菜單列表顯示的功能(如圖所示:左邊為菜單類別,右邊顯示相對(duì)應(yīng)的菜品)

vue如何監(jiān)聽(tīng)滾動(dòng)事件實(shí)現(xiàn)錨點(diǎn)鏈接平滑滾動(dòng)

小編將此分為三個(gè)功能模塊來(lái)實(shí)現(xiàn)(本來(lái)一張動(dòng)畫(huà)就清晰明了,小編太笨,只得口述一下):

1.左邊點(diǎn)擊類別,右邊顯示相應(yīng)類別的菜品列表(平滑滾動(dòng))
2.滾動(dòng)右邊的滾動(dòng)條,左邊對(duì)應(yīng)的顯示當(dāng)前樣式
3.若從別的頁(yè)面點(diǎn)擊菜品進(jìn)來(lái)該頁(yè)面,則該菜品為指定效果

小編也是vue的初學(xué)者,在閱讀了大量的文章后,其中借鑒https://www.jb51.net/article/110325.htm 該文章,收到了很多啟發(fā)后,結(jié)合我們的功能加以完善。小編的和借鑒的文章側(cè)重點(diǎn)不同,建議大家在看之前可以先看一下上面的,以便于梳理的更清楚。

:scrollTop(滾動(dòng)之根本)

在初寫(xiě)項(xiàng)目的嘗試過(guò)程中,小編一直改變的是document.body.scrollTop的值來(lái)實(shí)現(xiàn)滾動(dòng),但是后來(lái)逐漸發(fā)現(xiàn)很邪門(mén),有時(shí)給其賦值并沒(méi)有作用,而且過(guò)程也很麻煩,又查閱了一些資料也沒(méi)有解決辦法,所以不得已放棄。

之后無(wú)意中看到:scrollTop, 便嘗試開(kāi)始使用vue中的屬性直接進(jìn)行綁定滾動(dòng)的變量值,功能實(shí)現(xiàn)反而簡(jiǎn)單了。下面詳細(xì)講述:

一、組件html結(jié)構(gòu):

結(jié)構(gòu)布局很簡(jiǎn)單,在此多說(shuō)是想給大家講述清楚一點(diǎn)兒右邊菜品的結(jié)構(gòu),方便綁定:scrollTop屬性,小編就踩了這個(gè)坑...

vue如何監(jiān)聽(tīng)滾動(dòng)事件實(shí)現(xiàn)錨點(diǎn)鏈接平滑滾動(dòng)

注意看注釋::scrollTop 的位置改變菜品列表的scrollTop值,來(lái)實(shí)現(xiàn)相應(yīng)的滾動(dòng)

二、實(shí)現(xiàn)錨鏈接平滑滾動(dòng)

該功能是參考之前博主的文章的,方法基本沒(méi)改什么,簡(jiǎn)單易懂,直接放代碼

jump(index){
    const cateItem = document.querySelectorAll('.cate-item');
    let total = cateItem[index].offsetTop;
    let distance = this.container.scrollTop // 獲取到頂部的距離(this.container便是.cate-list,為了方便存起來(lái)了)
    let step = total / 50;
    this.isActive = index; // 菜單列表顯示當(dāng)前樣式
    const _this = this;
    if (total > distance) {
     smoothDown()
    } else {
     let newTotal = distance - total
     step = newTotal / 50
     smoothUp()
    }
    function smoothDown () {
     if (distance < total) {
     distance += step
     _this.scrollTop = distance;
     setTimeout(smoothDown, 10);
     } else {
     _this.scrollTop = total
     }
    }
    function smoothUp () {
     if (distance > total) {
     distance -= step
     _this.scrollTop = distance
     setTimeout(smoothUp, 10)
     } else {
     _this.scrollTop = total
     }
    } 
    }

三、監(jiān)聽(tīng)滾動(dòng)事件,修改錨點(diǎn)狀態(tài)

在vue中鉤子函數(shù)監(jiān)聽(tīng)菜品列表(this.container)的滾動(dòng)事件,

 mounted(){
   // 監(jiān)聽(tīng)scroll事件
   const _this = this;
   setTimeout(function(){
    _this.currentStick(); 
    const rightItem = document.querySelectorAll('.cate-item');
    const catelist = document.querySelectorAll('.cate-list')[0];
    var length = rightItem.length;
    var height = rightItem[length-1].offsetHeight;
    var scrollHeight = document.querySelectorAll('.cate-menu-wrapper')[0].offsetHeight;
    // 設(shè)置最后一個(gè)類別菜品列表的高度(小于適配器高度的話與適配器等高),不然點(diǎn)擊錨點(diǎn)不能夠置頂
    if(height < scrollHeight){
     rightItem[length-1].style.height = scrollHeight+'px';
    } 
    var arr =[];
    rightItem.forEach(function(v, i){
     arr.push({top: v.offsetTop, height: v.offsetHeight, index: i});
    })
    _this.itemVal = arr; 
    const cateList = document.querySelectorAll('.cate-list')[0];
    cateList.addEventListener('scroll', _this.onScroll);
    _this.container = cateList;
   }, 500)
  },

這里寫(xiě)的有點(diǎn)啰嗦了,設(shè)置setTimeout延遲是為了能夠獲取到元素(誰(shuí)有好辦法快推薦給我),為了在滾動(dòng)中能夠?qū)?yīng)列表顯示錨點(diǎn)當(dāng)前狀態(tài),存了一個(gè)數(shù)據(jù)itemAll,存了該菜品類別區(qū)域的scrollTop,索引,高度。(啰嗦,太啰嗦了)

methods: {
 onScroll () {
    var _this = this;
    _this.itemVal.forEach(function(obj, i){
     _this.scrollTop = _this.container.scrollTop;
     if(_this.scrollTop >= obj.top && _this.scrollTop < (obj.top + obj.height-10)){
      // scrollTop的移動(dòng)位置要在類別的菜品列表中才顯示對(duì)應(yīng)錨點(diǎn)的當(dāng)前狀態(tài)
      _this.isActive = obj.index;
     }
    })
   },
}

三、點(diǎn)擊菜品進(jìn)入頁(yè)面,該菜品置頂?shù)穆?lián)動(dòng)效果(該功能其實(shí)有隱藏性的bug,我們項(xiàng)目已取消該功能)

currentStick(){
     const {dishId} = this.$route.query;
     const cateContent = document.querySelectorAll('.cate-content');
     const _this = this;
     cateContent.forEach(function(v, i){
      if(v.id == dishId){
       _this.scrollTop = v.offsetTop; 
      }
     })
   },

該功能用:scrollTop綁定的話便簡(jiǎn)單了許多,之前用document.body.scrollTop 設(shè)置值一直沒(méi)有作用。

好了,基本上所有的代碼都帖出來(lái)了,說(shuō)的應(yīng)該也詳細(xì)吧(我盡力了),該方法感覺(jué)其實(shí)還是在操作dom元素和js,枉用vue。但是一時(shí)也沒(méi)有更好的辦法來(lái)實(shí)現(xiàn)。

關(guān)于“vue如何監(jiān)聽(tīng)滾動(dòng)事件實(shí)現(xiàn)錨點(diǎn)鏈接平滑滾動(dòng)”這篇文章就分享到這里了,希望以上內(nèi)容可以對(duì)大家有一定的幫助,使各位可以學(xué)到更多知識(shí),如果覺(jué)得文章不錯(cuò),請(qǐng)把它分享出去讓更多的人看到。

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

vue
AI