基于vue監(jiān)聽(tīng)滾動(dòng)事件實(shí)現(xiàn)錨點(diǎn)鏈接平滑滾動(dòng)的方法
基于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)的菜品)
小編將此分為三個(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é)者,在閱讀了大量的文章后,其中借鑒http://www.dbjr.com.cn/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)很邪門,有時(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è)坑...
注意看注釋::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)。
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
- vue使用@scroll監(jiān)聽(tīng)滾動(dòng)事件時(shí),@scroll無(wú)效問(wèn)題的解決方法詳解
- vue回到頂部監(jiān)聽(tīng)滾動(dòng)事件詳解
- vue實(shí)現(xiàn)某元素吸頂或固定位置顯示(監(jiān)聽(tīng)滾動(dòng)事件)
- vue監(jiān)聽(tīng)滾動(dòng)事件實(shí)現(xiàn)滾動(dòng)監(jiān)聽(tīng)
- Vue.js實(shí)戰(zhàn)之通過(guò)監(jiān)聽(tīng)滾動(dòng)事件實(shí)現(xiàn)動(dòng)態(tài)錨點(diǎn)
- vue監(jiān)聽(tīng)滾動(dòng)事件的方法
相關(guān)文章
vue3?+?antv/x6實(shí)現(xiàn)流程圖的全過(guò)程
隨著互聯(lián)網(wǎng)的發(fā)展,越來(lái)越多的應(yīng)用需要實(shí)現(xiàn)流程圖的制作,如工作流程圖、電路圖等,文中通過(guò)代碼以及圖文將實(shí)現(xiàn)的過(guò)程介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)或者工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2024-06-06vue3中調(diào)用api接口實(shí)現(xiàn)數(shù)據(jù)的渲染以及詳情方式
這篇文章主要介紹了vue3中調(diào)用api接口實(shí)現(xiàn)數(shù)據(jù)的渲染以及詳情方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-08-08詳解vue數(shù)組遍歷方法forEach和map的原理解析和實(shí)際應(yīng)用
這篇文章主要介紹了詳解vue數(shù)組遍歷方法forEach和map的原理解析和實(shí)際應(yīng)用,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2018-11-11關(guān)于vue-resource報(bào)錯(cuò)450的解決方案
本篇文章主要介紹關(guān)于vue-resource報(bào)錯(cuò)450的解決方案,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-07-07vuex 解決報(bào)錯(cuò)this.$store.commit is not a function的方法
這篇文章主要介紹了vuex 解決報(bào)錯(cuò)this.$store.commit is not a function的方法,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2018-12-12laravel5.3 vue 實(shí)現(xiàn)收藏夾功能實(shí)例詳解
這篇文章主要介紹了laravel5.3 vue 實(shí)現(xiàn)收藏夾功能,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),需要的朋友可以參考下2018-01-01vue項(xiàng)目總結(jié)之文件夾結(jié)構(gòu)配置詳解
這篇文章主要給大家總結(jié)介紹了關(guān)于vue項(xiàng)目之文件夾結(jié)構(gòu)配置的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧。2017-12-12Vant實(shí)現(xiàn)上傳多個(gè)圖片或視頻,更改視頻預(yù)覽圖
這篇文章主要介紹了Vant實(shí)現(xiàn)上傳多個(gè)圖片或視頻,更改視頻預(yù)覽圖,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-10-10