在开发中常常会遇到这样一个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++) {
let offset_before = this.$el.querySelector("#xqItem" + i).offsetTop; //offsetTop: 获取当前元素到其定位父级(offsetParent)的顶部距离
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,并让左边的目录树中对应的节点高亮显示”这个功能便实现了。

vue监听页面中的某个div的滚动事件,并判断滚动的位置的更多相关文章

  1. 监听页面中的某个div的滚动事件,并将其滚动距离保存到cookie

    在html中,写一个id为type的div: <div class="type" id="type"></div> css: .type ...

  2. vue 监听页面宽度变化 和 键盘事件

    vue 监听页面窗口大小 export default { name: 'Full', components: { Header, Siderbar }, data () { return { scr ...

  3. vue监听页面大小变化重新刷新布局

    在项目中由于某些div元素在布局的时候需要初始化宽高,因为当浏览器缩小屏幕的时候需要重新刷新页面视图. 分析思路: 1.在store中创建state,用于保存当前浏览器的宽.高值. 2.在mounte ...

  4. vue监听数组中某个属性,计算其他属性问题

    今天在项目开发中遇到一个根据数组中某个属性变化同时更新另一个属性变化的问题,刚开始代码如下 this.weekList1=r.data.roomProducts; this.weekList1.map ...

  5. vue 监听store中的数值

      computed: {   isFollow () {     return this.$store.state.demo.id; //需要监听的数据   } }, watch: {   isFo ...

  6. js给页面添加滚动事件并判断滚动方向

    <script> var scrollFunc = function (e) { var direct = 0; e = e || window.event; if (e.wheelDel ...

  7. Vue - 监听页面刷新和关闭

    一,在 created中 注册 页面刷新和关闭事件 created() {  window.addEventListener('beforeunload', e => this.test(e)) ...

  8. vue中监听页面滚动和监听某元素滚动

    ①监听页面滚动 在生命周期mounted中进行监听滚动: mounted () { window.addEventListener('scroll', this.scrollToTop) }, 在方法 ...

  9. vue 中监听页面滚动

    监听页面滚动 在methods中定义一个方法 handleScroll() { //获取滚动时的高度 let scrollTop = window.pageYOffset || document.do ...

随机推荐

  1. CSS样式表的书写位置

    行内式(内联样式) 是通过标签的style属性来设置元素的样式,其基本语法格式如下: <标签名 style="属性1:属性值1; 属性2:属性值2; 属性3:属性值3;"&g ...

  2. Java&Tomcat环境变量配置

    版本匹配: Java PATH环境变量.作用是指定命令搜索路径,在shell下面执行命令时,它会到PATH变量所指定的路径中查找看是否能找到相应的命令程序.我们需要把 jdk安装目录下的bin目录增加 ...

  3. Nvicat for mysql连接腾讯云数据库TDSQL-C(原CynosDB)

    连接步骤 1.打开腾讯云TDSQL-C(原CynosDB)集群详情中的中的集群连接外网地址,如下图 2.云数据库的账号密码在这里找,第一次不知道密码可以重置密码 3.以root账户为例,打开navic ...

  4. 编译安装 tree 命令

    文章目录 下载源码包 编译源码包 tree下载地址:http://mama.indstate.edu/users/ice/tree/ Centos发行版,可以直接使用命令 yum -y install ...

  5. c++ Message与Folder 拷贝 析构(没有动态空间的类)

    c++ Message与Folder 拷贝 析构(没有动态空间的类) 1.两个类里边分别保存一个对方的set表,当前类有拷贝或者销毁时需要更新另一个类的set表. 2.两个类都需要访问对方的priva ...

  6. python3发邮件脚本

    官方文档中建议保存token,且token是每2小时更新一次. 所以token先保存在本地token.txt文件夹中,设定计划任务每1小时删除一下token.txt.虽然造成了浪费,对于发消息不多的人 ...

  7. CobaltStrike逆向学习系列(12):RDI 任务发布流程分析

    这是[信安成长计划]的第 12 篇文章 0x00 目录 0x01 任务构建 0x02 结果处理 0x03 功能 DLL 分析 之前的分析都是针对整个 CS 的框架来进行的,但是功能也是整个 C2 中相 ...

  8. BUUCTF-jarvisoj_level0

    因为最近正在学习pwn,所以一直在各种CTF平台刷题,(因为初学,目前刷的一下题目都是相较于入门) 下载附件丢到kali里面checksec检测一下, 有一个NX,然后放到IDA,直接shift+f1 ...

  9. 好久没写作业了,因为组里分配了任务,学习了Resnet和DenseNet,把概要po上来和大家分享。

    Res: 学长说,不要看别人的博客.看多了就看傻了!俗话说,不听老人言,吃亏在眼前. 第一篇论文来咯!Deep Residual Learning for Image Recognition!国人写的 ...

  10. 【信而泰】网络损伤仿真,为5G应用保驾护航

    5G,绝对是今年最热门的话题!2019年6月6日,工信部正式向中国电信.中国移动.中国联通.中国广电发放5G商用牌照,中国正式进入5G商用元年.5G不仅仅是一次通信技术的升级,更是开启了一个新的时代. ...