vue監(jiān)聽(tīng)頁(yè)面中的某個(gè)div的滾動(dòng)事件并判斷滾動(dòng)的位置
在開(kāi)發(fā)中常常會(huì)遇到這樣一個(gè)vue頁(yè)面,頁(yè)面分為左右兩部分,左邊是目錄樹(shù),右邊是一個(gè)類(lèi)名為xq-box的div,在xq-box中多個(gè)div上下并列布局,每個(gè)div中的內(nèi)容就對(duì)應(yīng)著左邊目錄樹(shù)中的相應(yīng)節(jié)點(diǎn),現(xiàn)在的目標(biāo)是,要監(jiān)聽(tīng)這個(gè)xq-box滾動(dòng)事件,右邊一旦開(kāi)始滾動(dòng),就要知道滾動(dòng)到哪個(gè)子div,并讓左邊的目錄樹(shù)中對(duì)應(yīng)的節(jié)點(diǎn)高亮顯示。要怎么做呢?
1、首先,先寫(xiě)好大概的頁(yè)面布局,這里要注意,右邊xq-box的子div要綁定"'xqItem'+序號(hào)"的id,為了下面用js能獲取到匹配的dom元素:
<template> <div class="container"> <div class="left-box"> <div class="menu-box"> <div class="menu-title"> <p>目錄</p> </div> <div class="menu-item" v-for="(menu, index) in menuList" :key="index" :class="{ 'active': menuActive === index }" @click="chooseMenu(menu.name, index)" > <img :src="menu.icon" class="menu-icon" /> <p>{{ menu.name }}</p> </div> </div> </div> <div class="right-box"> <div class="xq-box" ref="xqBox"> <div class="xq-item" :id="'xqItem' + index" v-for="(item, index) in xqConList" :key="index" > <!--這里渲染出目錄內(nèi)容--> <div class="xq-item-name"> {{ item.name }} </div> <div class="xq-item-con"> {{ item.content }} </div> </div> </div> </div> </div> </template>
2、然后,在css里給xq-box高度,設(shè)置其超出能滾動(dòng):
<style lang="stylus" scoped> .right-box height 600px .xq-box height 100% overflow-y auto <style>
3、接著,在計(jì)算屬性獲取到這個(gè)ref="xqBox"的dom元素,寫(xiě)一個(gè)函數(shù)handleScroll()獲取滾動(dòng)距離并判斷滾動(dòng)到哪兩個(gè)子div之間,并在頁(yè)面渲染完后監(jiān)聽(tīng)這個(gè)xq-box的滾動(dòng)事件。
export default { name: "menuList", data() { return { menuActive: 0, //左側(cè)高亮的item menuList: [], //左側(cè)目錄樹(shù) xqConList: [] //右側(cè)目錄內(nèi)容列表 } }, computed: { xqBox() { return this.$refs.xqBox; } }, mounted() { this.$nextTick(() => { // //監(jiān)聽(tīng)這個(gè)dom的scroll事件 // this.xqBox.onscroll = () => { // console.log("on scroll"); // this.handleScroll(); // }; //監(jiān)聽(tīng)這個(gè)dom的scroll事件 this.xqBox.addEventListener("scroll", this.handleScroll); }); }, methods: { handleScroll() { //獲取dom滾動(dòng)距離 const scrollTop = this.xqBox.scrollTop; //獲取可視區(qū)高度 const offsetHeight = this.xqBox.offsetHeight; //獲取滾動(dòng)條總高度 const scrollHeight = this.xqBox.scrollHeight; //xqConList 為目錄內(nèi)容列表 for (let i = 0; i < this.xqConList.length - 1; i++) { //offsetTop: 獲取當(dāng)前元素到其定位父級(jí)(offsetParent)的頂部距離 let offset_before = this.$el.querySelector("#xqItem" + i).offsetTop; let offset_after = this.$el.querySelector("#xqItem" + (i + 1)) .offsetTop; //根據(jù)xqItem離頂部距離判斷滾動(dòng)距離落在哪兩個(gè)item之間 if (scrollTop >= offset_before && scrollTop < offset_after) { // console.log("offset", offset_before, offset_after, scrollTop); // console.log("scrollHeight", scrollTop, offsetHeight, scrollHeight); //判斷是否滾動(dòng)到了底部 if (scrollTop + offsetHeight >= scrollHeight) { // 把距離頂部的距離加上可視區(qū)域的高度 等于或者大于滾動(dòng)條的總高度就是到達(dá)底部 // console.log("已滾動(dòng)到底部"); if (this.menuActive < i) { this.menuActive = i; } } else { this.menuActive = i; } break; } } }, } };
經(jīng)查詢(xún)得知,Vue組件在patch階段結(jié)束時(shí)會(huì)把this.$el賦值為掛載的根dom元素,我們可以直接使用$el的querySelector, querySelectorAll等方法獲取匹配的元素。因1中每個(gè)內(nèi)容塊子div已經(jīng)綁定id,所以此處可以用 this.$el.querySelector("#xqItem" + i) 獲取到每個(gè)子div。
還有一個(gè)要注意的是,這里之所以要判斷是否滾動(dòng)到了底部,是因?yàn)閤q-box一旦滾動(dòng)到底部,就可以看到最后幾個(gè)目錄對(duì)應(yīng)的子div,此時(shí)的滾動(dòng)距離scrollTop只會(huì)落在這最后幾個(gè)子div的第一個(gè)子div(序號(hào)即當(dāng)前本次循環(huán)中的i)的離頂部距離位置上,這個(gè)時(shí)候如果左側(cè)目錄樹(shù)高亮的正好是這最后幾個(gè)目錄的其中任意一個(gè),則無(wú)需更改高亮;但是如果此時(shí) this.menuActive 的值還比最后幾個(gè)子div中的第一個(gè)的序號(hào)要小,即比本次循環(huán)的 i 要小,則需要更改為當(dāng)前的 i 值。
4、如果要點(diǎn)擊左邊目錄樹(shù),右邊xq-box也要自動(dòng)滾動(dòng)到相應(yīng)的目錄內(nèi)容,則要增加以下方法:
chooseMenu(name, index) { this.menuActive = index; // //可以用scrollIntoView // document.querySelector("#xqItem" + index).scrollIntoView({ // block: "start", // behavior: "smooth" // }); let offsetTop = this.$el.querySelector("#xqItem" + index).offsetTop; console.log("#xqItem" + index + " offsetTop: " + offsetTop); this.xqBox.scrollTop = this.$el.querySelector( "#xqItem" + index ).offsetTop; },
這樣,“監(jiān)聽(tīng)這個(gè)xq-box滾動(dòng)事件,右邊一旦開(kāi)始滾動(dòng),就要知道滾動(dòng)到哪個(gè)子div,并讓左邊的目錄樹(shù)中對(duì)應(yīng)的節(jié)點(diǎn)高亮顯示”這個(gè)功能便實(shí)現(xiàn)了。
到此這篇關(guān)于vue監(jiān)聽(tīng)頁(yè)面中的某個(gè)div的滾動(dòng)事件并判斷滾動(dòng)的位置的文章就介紹到這了,更多相關(guān)vue監(jiān)聽(tīng)div滾動(dòng)事件 內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
詳解從零搭建 vue2 vue-router2 webpack3 工程
本篇文章主要介紹了詳解從零搭建 vue2 vue-router2 webpack3 工程,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-11-11vue用復(fù)選框?qū)崿F(xiàn)組件且支持單選和多選操作方式
這篇文章主要介紹了vue用復(fù)選框?qū)崿F(xiàn)組件且支持單選和多選操作方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-04-04細(xì)說(shuō)Vue組件的服務(wù)器端渲染的過(guò)程
這篇文章主要介紹了細(xì)說(shuō) Vue 組件的服務(wù)器端渲染,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2019-05-05element--Diaolog彈窗打開(kāi)之后渲染組件方式
這篇文章主要介紹了element--Diaolog彈窗打開(kāi)之后渲染組件方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-01-01vue如何設(shè)置定時(shí)器和清理定時(shí)器
這篇文章主要介紹了vue如何設(shè)置定時(shí)器和清理定時(shí)器,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-05-05Vue中實(shí)現(xiàn)v-for循環(huán)遍歷圖片的方法
這篇文章主要介紹了Vue中實(shí)現(xiàn)v-for循環(huán)遍歷圖片的方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-08-08