vue监听页面中的某个div的滚动事件并判断滚动的位置

作者:翀上云霄 时间:2024-05-09 15:08:49 

  在开发中常常会遇到这样一个vue页面,页面分为左右两部分,左边是目录树,右边是一个类名为xq-box的div,在xq-box中多个div上下并列布局,每个div中的内容就对应着左边目录树中的相应节点,现在的目标是,要监听这个xq-box滚动事件,右边一旦开始滚动,就要知道滚动到哪个子div,并让左边的目录树中对应的节点高亮显示。要怎么做呢?

1、首先,先写好大概的页面布局,这里要注意,右边xq-box的子div要绑定"'xqItem'+序号"的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"
             >
                <!--这里渲染出目录内容-->
                <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高度,设置其超出能滚动:

<style lang="stylus" scoped>
 .right-box
     height 600px
     .xq-box
         height 100%
         overflow-y auto
<style>

3、接着,在计算属性获取到这个ref="xqBox"的dom元素,写一个函数handleScroll()获取滚动距离并判断滚动到哪两个子div之间,并在页面渲染完后监听这个xq-box的滚动事件。

export default {
 name: "menuList",
 data() {
   return {
     menuActive: 0,  //左侧高亮的item
     menuList: [],  //左侧目录树
     xqConList: []  //右侧目录内容列表
   }
 },
 computed: {
   xqBox() {
     return this.$refs.xqBox;
   }
 },
 mounted() {
   this.$nextTick(() => {
     // //监听这个dom的scroll事件
     // this.xqBox.onscroll = () => {
     //   console.log("on scroll");
     //   this.handleScroll();
     // };
     //监听这个dom的scroll事件
     this.xqBox.addEventListener("scroll", this.handleScroll);
   });
 },
 methods: {
   handleScroll() {
     //获取dom滚动距离
     const scrollTop = this.xqBox.scrollTop;
     //获取可视区高度
     const offsetHeight = this.xqBox.offsetHeight;
     //获取滚动条总高度
     const scrollHeight = this.xqBox.scrollHeight;
     //xqConList 为目录内容列表
     for (let i = 0; i < this.xqConList.length - 1; i++) {
       //offsetTop: 获取当前元素到其定位父级(offsetParent)的顶部距离
       let offset_before = this.$el.querySelector("#xqItem" + i).offsetTop;  
       let offset_after = this.$el.querySelector("#xqItem" + (i + 1))
         .offsetTop;

//根据xqItem离顶部距离判断滚动距离落在哪两个item之间
       if (scrollTop >= offset_before && scrollTop < offset_after) {
         // console.log("offset", offset_before, offset_after, scrollTop);
         // console.log("scrollHeight", scrollTop, offsetHeight, scrollHeight);
         //判断是否滚动到了底部
         if (scrollTop + offsetHeight >= scrollHeight) {
           // 把距离顶部的距离加上可视区域的高度 等于或者大于滚动条的总高度就是到达底部
           // console.log("已滚动到底部");
           if (this.menuActive < i) {
             this.menuActive = i;
           }
         } else {
           this.menuActive = i;
         }
         break;
       }
     }
   },
 }
};

       经查询得知,Vue组件在patch阶段结束时会把this.$el赋值为挂载的根dom元素,我们可以直接使用$el的querySelector, querySelectorAll等方法获取匹配的元素。因1中每个内容块子div已经绑定id,所以此处可以用 this.$el.querySelector("#xqItem" + i) 获取到每个子div。

       还有一个要注意的是,这里之所以要判断是否滚动到了底部,是因为xq-box一旦滚动到底部,就可以看到最后几个目录对应的子div,此时的滚动距离scrollTop只会落在这最后几个子div的第一个子div(序号即当前本次循环中的i)的离顶部距离位置上,这个时候如果左侧目录树高亮的正好是这最后几个目录的其中任意一个,则无需更改高亮;但是如果此时 this.menuActive 的值还比最后几个子div中的第一个的序号要小,即比本次循环的 i 要小,则需要更改为当前的 i 值。

4、如果要点击左边目录树,右边xq-box也要自动滚动到相应的目录内容,则要增加以下方法:

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;
},

这样,&ldquo;监听这个xq-box滚动事件,右边一旦开始滚动,就要知道滚动到哪个子div,并让左边的目录树中对应的节点高亮显示&rdquo;这个功能便实现了。

来源:https://www.cnblogs.com/chong0668-2013/p/16017470.html

标签:vue,监听,div,滚动
0
投稿

猜你喜欢

  • SQL Server中常用截取字符串函数介绍

    2024-01-25 16:34:02
  • wxPython中wx.gird.Gird添加按钮的实现

    2021-07-05 15:13:19
  • MySQL数据库优化之分表分库操作实例详解

    2024-01-20 10:33:53
  • 如何用idea数据库编写快递e站

    2024-01-23 08:43:56
  • 电子商务搜索LIST页面用户体验设计

    2010-08-03 12:57:00
  • python字符串连接方法分析

    2021-12-24 16:27:10
  • python实现超简单端口转发的方法

    2022-12-25 04:00:53
  • asp随机获取access数据库中的一条记录

    2007-08-15 13:11:00
  • Python+pyecharts绘制双动态曲线教程详解

    2023-03-04 09:19:48
  • MySQL定位并优化慢查询sql的详细实例

    2024-01-25 20:32:16
  • 解决MYSQL出现Can't create/write to file '/tmp/#sql_5c0_0.MYD'的问题

    2024-01-16 07:53:39
  • Web开发的改良

    2009-06-25 14:34:00
  • Python拼接字符串的7种方法总结

    2022-10-28 08:38:00
  • 关于vue-router路径计算问题

    2024-05-13 09:07:32
  • vue中el-table两个表尾合计行联动同步滚动条实例代码

    2023-07-02 17:08:56
  • mysql 分页优化解析

    2024-01-15 00:33:40
  • JScript 运算符

    2007-08-22 16:22:00
  • python 服务器批处理得到PSSM矩阵的问题

    2021-05-19 12:21:13
  • JavaScript实现相册弹窗功能(zepto.js)

    2024-04-19 10:42:49
  • Javascript中常见的逻辑题和解决方法

    2024-05-22 10:31:21
  • asp之家 网络编程 m.aspxhome.com