在开发中常常会遇到这样一个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. 使用CAShapeLayer做出圆形的进度条 —— #DF!

    CircleView.h的内容如下: #import <UIKit/UIKit.h> @interface CircleView : UIView @property (nonatomic ...

  2. 动态路由与RIP协议

    动态路由与RIP协议 目录 动态路由与RIP协议 一.动态路由(Dynamic Route) 1.动态路由概述 2.动态路由特点 3.动态路由协议 (1)动态路由协议概述 (2)度量值 (3)收敛 4 ...

  3. 《PHP程序员面试笔试宝典》——在被企业拒绝后是否可以再申请?

    如何巧妙地回答面试官的问题? 本文摘自<PHP程序员面试笔试宝典> 很多企业为了能够在一年一度的招聘季节中,提前将优秀的程序员锁定到自己的麾下,往往会先下手为强.他们通常采取的措施有两种: ...

  4. LNK善意利用

    lnk   lnk在Windows平台下是快捷方式,可以指向其他目录下的文件,并且可以传递参数.现在有些恶意活动会恶意利用lnk,执行恶意代码.   关于lnk的格式,可以使用010 editor的模 ...

  5. kube-scheduler源码分析(1)-初始化与启动分析

    kube-scheduler源码分析(1)-初始化与启动分析 kube-scheduler简介 kube-scheduler组件是kubernetes中的核心组件之一,主要负责pod资源对象的调度工作 ...

  6. Numpy的各种下标操作

    技术背景 本文所使用的Numpy版本为:Version: 1.20.3.基于Python和C++开发的Numpy一般被认为是Python中最好的Matlab替代品,其中最常见的就是各种Numpy矩阵类 ...

  7. SpringCloud微服务实战——搭建企业级开发框架(三十八):搭建ELK日志采集与分析系统

      一套好的日志分析系统可以详细记录系统的运行情况,方便我们定位分析系统性能瓶颈.查找定位系统问题.上一篇说明了日志的多种业务场景以及日志记录的实现方式,那么日志记录下来,相关人员就需要对日志数据进行 ...

  8. [Python]小白入门时遇到的各种问题

    Q:关于Python2.X和Python3.X各种版本有什么区别,小白应该选哪个? A: 1.背景及简要介绍 Python 2 发布于 2000 年年底. 随着 Python 2 的不断发展,更多的功 ...

  9. mysql 的奇妙历险

    mysql 的奇妙历险 这几天在练习sql的时候,碰到下面几个题, 如下 他的表字段是这些 create table Student( SId varchar(10), # 学生id Sname va ...

  10. 【C# TAP 异步编程】二 、await运算符已经可等待类型Awaitable

    await的作用: 1.await是一个标记,告诉编译器生成一个等待器来等待可等待类型实例的运行结果. 2.一个await对应一个等待器 ,任务的等待器类型是TaskAwaiter/TaskAwait ...