
总体代码演示
*** !!!注意本组件只允许放在需要监听滚动页面的最底部,因为我们是通过父元素的节点获得内部所有子元素的高度所以必须要放在父元素中的最底部***
子组件“appsideNavBar”代码如下(示例):
<template>
<ul class="side-navBar">
<li
@click="itemClick(index)"
v-for="(item, index) in navLists"
:key="index"
:class="moveIndex === index ? 'activeLight' : ''"
>
{{ item }}
</li>
</ul>
</template>
<script>
// !!!注意本组件只允许放在需要监听滚动页面的最底部,因为我们是通过父元素的节点获得内部所有子元素的高度所以必须要放在父元素中的最底部
export default {
props: {
navLists: Array //每个标题内容
},
data() {
return {
moveIndex: 0, //当前激活nav栏高亮显示标题的下标
ContentHeightList: null //页面中每一栏内容的高度数组
};
},
methods: {
// 点击nav栏后
itemClick(index) {
// 获取父元素的dom元素
let pageScrooll = document.querySelector(".side-navBar").parentNode;
// console.log(pageScrooll.children[index].offsetTop + 520);
// 激活当前高亮nav栏
this.moveIndex = index;
// 点击后滚动到相应的区域
window.scrollTo({
top: pageScrooll.children[index].offsetTop, //举例:用户点击 第二个标签后 页面就会滚动到第二个标签的高度
behavior: "smooth" //丝滑滚动
});
},
// 获取页面中每一栏内容的高度数组
getChildrenHeigh() {
// 获得他们的父元素节点
let pageScrooll = document.querySelector(".side-navBar").parentNode;
let arr = [];
// console.log(this.navLists.length);
// 将所有子元素的高度放入arr
for (let i = 0; i < this.navLists.length; i++) {
// 把所有获得到的子元素高度都放入arr中
arr.push(pageScrooll.children[i].offsetTop);
}
// 给这个arr兜底,这样可以解决最后一个内容栏监听不到的bug,注意:如果最后一栏内容高度低于滚动条当前的高度,也不会高亮显示最后一栏的标题哦
arr.push(Number.MAX_VALUE);
this.ContentHeightList = arr;
// console.log(this.ContentHeightList);
},
// 监听滚轮
handleScroll() {
// 获得当前的滚轮高度
var scrollTop =
window.pageYOffset ||
document.documentElement.scrollTop ||
document.body.scrollTop;
console.log('scrollTop---', scrollTop)
let Heights = this.ContentHeightList;
// 只有ContentHeightList存在才监听当前高度
if (this.ContentHeightList) {
// console.log(scrollTop);
for (let i = 0; i < Heights.length; i++) {
// 如果滚轮高度大于当前所在的子元素高度 并且 滚轮高度小于下一个子元素的高度 ,那么说明滚轮在当前内容中,就激活当前的nav栏
if (scrollTop >= Heights[i] && scrollTop <= Heights[i + 1]) {
// console.log(i);
// 那么就激活当前的nav栏
this.moveIndex = i;
// return false;
}
}
}
}
},
mounted() {
// JS原生方法:监听滚动
window.addEventListener("scroll", this.handleScroll, true);
// 获得内容高度
this.getChildrenHeigh();
},
destroyed() {
this.ContentHeightList = null;
// 切换路由以后依旧其他页面也触发了scrollHandler函数,然后我想到使用了vue-router做的spa项目,window对象不变的,所以需要在每次使用后销毁
window.removeEventListener("scroll", this.handleScroll, true);
}
};
</script>
<style lang="less" scoped>
.side-navBar {
transition: 0.5s linear all;
position: fixed;
top: 280px;
left: 0px; //改为right 就是右侧边栏
width: 130px;
background: #ffffff;
box-shadow: 0px 2px 6px 0px rgba(0, 0, 0, 0.2);
border-radius: 0px 10px 10px 0px;
z-index: 99999;
padding: 43px 0 0 0;
li {
margin-bottom: 40px;
font-size: 14px;
font-family: PingFangSC-Regular, PingFang SC;
font-weight: 400;
color: rgba(0, 0, 0, 0.85);
line-height: 20px;
cursor: pointer;
padding-left: 43px;
position: relative;
}
}
.activeLight {
color: #096dd9 !important;
}
</style>
父组件代码如下(示例):
<template>
<div class="demo">
<div class="container" style=" background-color: #eee;" v-for="item in navLists" :key="item">{{item}}</div>
<appsideNavBar :navLists="navLists"></appsideNavBar>
<div style="height:500px"></div>
</div>
</template>
<script>
import appsideNavBar from './AppsideNavBar.vue'
export default {
components:{
appsideNavBar
},
data() {
return {
//nav栏的文字
navLists: ["标题1", "标题2", "标题3", "标题4","标题5"],
}
}
}
</script>
<style scoped>
.container {
width: 100%;
height: 600px;
font-size: 80px;
display: flex;
justify-content: center;
align-items: center;
border: 2px solid black;
}
</style>
网页可见区域高:document.body.clientHeight
网页正文全文高:document.body.scrollHeight
网页可见区域高(包括边线的高):document.body.offsetHeight
网页被卷去的高:document.body.scrollTop
屏幕分辨率高:window.screen.height
原文链接:https://blog.csdn.net/m0_68324632/article/details/125988195