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;
},
这样,“监听这个xq-box滚动事件,右边一旦开始滚动,就要知道滚动到哪个子div,并让左边的目录树中对应的节点高亮显示”这个功能便实现了。
来源:https://www.cnblogs.com/chong0668-2013/p/16017470.html


猜你喜欢
- 后台数据库用是Access,客户用了一年后说打开界面非常慢,查看了数据库后发现数据表中的记录已有五万多条,自己试过将记录复制到10 万条,打
- 微信小程序-拍照或选择图片并上传文件调用拍照API:https://mp.weixin.qq.com/debug/wxadoc/dev/ap
- 通过学习私有函数与私有变量,可以更好的完善 类的开发 ,从而丰满我们的场景与实现方案。什么是私有函数和私有变量私有函数与私有变量中的私有是什
- 微信小程序 报错:this.setData is not a function在page中定义的代码如下,代码会报错:this.setDat
- 上一章节我们学习了基础的定义 PPT 的方法以及每一页中的样式,这节课我们将真正的在 PPT 中添加内容,学习一下 pptx 的段落的使用。
- ASP * 页制作中连接Oracle数据库的例子,下面这段代码能够显示,当前用户所能够看到的所有的用户和表,有兴趣的, 可以把每个表的内容上
- 经过总结,Python创建多线程主要有如下两种方法:函数类接下来,我们就来揭开多线程的神秘面纱。1. 用函数创建多线程在Python3中,P
- 本文实例讲述了flask框架jinja2模板与模板继承。分享给大家供大家参考,具体如下:jinja2模板from werkzeug.cont
- 在没步入正轨之前,先给大家介绍JavaScript 特殊字符你可以在 JavaScript 中使用反斜杠来向文本字符串添加特殊字符。插入特殊
- ASP中的全角和半角转化函数,使用方法,传入要转换的字符给str即可,flag设置要转换的类型。<% Function&n
- 1. 用户必须在几秒钟知道网站是做什么的。注意力是因特网上最有价值的货币。 如果访问者无法在几秒钟之内得知你的网站的方向,他很有可能转而访问
- #共有方法 + * instra='人生苦短'strb='我用python'lista=list(range
- 关于建立索引的几个准则:1、合理的建立索引能够加速数据读取效率,不合理的建立索引反而会拖慢数据库的响应速度。2、索引越多,更新数据的速度越慢
- 相比较pandas,numpy并没有很直接的rolling方法,但是numpy 有一个技巧可以让NumPy在C代码内部执行这种循环。这是通过
- 自定义函数参数传递为 字符串格式 ,传递方式1:用this传递 2:引号缺省 3:转义字符(html中 " 代表"
- 小编想把用python将列表[1,1,1,1,1,1,1,1,1,1] 和 列表 [2,2,2,2,2,2,2,2,2,2]对应相加成[3,
- 前言help(argparse)查看说明文档,“argparse - Command-line parsing libr
- 替换print?print怎么了?print 可能是所有学习Python语言的人第一个接触的东西。它最主要的功能就是往控制台 打印一段信息,
- 不同点: 1. truncate和 delete只删除数据不删除表的结构(定义) &
- 之前已经go get安装了gin, 现在来玩下用go gin server作图片上传服务, 代码目录如下:taoge:~/test_gin$