实现效果:点击侧边栏,右侧内容能够自动滑动到显示区域
滚动显示区域,侧边栏能够跟随高亮
代码如下:
<template>
<div class="root">
<div class="slidebar">
<ul class="sidebar-anchor-list">
<li
class="sidebar-anchor-item"
:class="{ active: item.anchor === anchor }"
v-for="item in anchorList"
@click="anchorPosition(item.anchor)"
>
<a class="sidebar-anchor-item-link">
<span class="sidebar-anchor-item-text">{{ item.text }}</span>
</a>
</li>
</ul>
</div>
<div class="main" id="main">
<div class="page-container" v-for="item in anchorList" :key="item.anchor" :id="item.anchor.replace(/#/g, '')">
{{ item.text }}
</div>
</div>
</div>
</template>
<script>
import _ from 'lodash';
export default {
data() {
return {
anchorList: [
{
anchor: '#labs',
text: '实验室',
},
{
anchor: '#courses',
text: '学好课',
},
{
anchor: '#project',
text: '好作品',
},
{
anchor: '#codingnews',
text: '资讯',
},
{
anchor: '#cocase',
text: '校园',
},
{
anchor: '#cooperator',
text: '合作',
},
],
anchor: '#labs',
offsetTopList: [],
};
},
mounted() {
this.$nextTick(() => {
this.setOffsetTopList();
document.getElementById('main').addEventListener('scroll', _.debounce(this.scrollHandle.bind(this), 20));
});
},
methods: {
anchorPosition(val) {
this.anchor = val;
this.scrollTo(val);
},
//获取每个模块距离顶部的距离
setOffsetTopList() {
const mainEl = document.querySelector('#main');
this.offsetTopList = this.anchorList.map((item, index) => {
const element = document.querySelector(item.anchor);
return {
offsetTop: index === 0 ? mainEl.offsetTop : element.offsetTop,
anchor: item.anchor,
};
});
console.log(this.offsetTopList);
},
scrollHandle({ target }) {
const curScrollTop = target.scrollTop;
const len = this.offsetTopList.length;
for (let i = len - 1; i >= 0; i--) {
const curReference = this.offsetTopList[i].offsetTop; // 当前参考值
if (curScrollTop >= curReference - 10) {
this.anchor = this.offsetTopList[i].anchor;
break;
}
}
},
scrollTo(anchor) {
const element = document.querySelector(anchor);
const parent = document.querySelector('#main');
parent.scrollTo({
top: element.offsetTop,
behavior: 'smooth',
});
},
},
};
</script>
<style lang="scss" scoped>
* {
list-style: none;
padding: 0;
margin: 0;
}
.root {
width: 100%;
height: 100%;
display: flex;
}
.slidebar {
width: 200px;
height: fit-content;
background-color: #f0f0f0;
margin-top: 30px;
.sidebar-anchor-item {
height: 68px;
border-bottom: 1px solid #eff3f8;
display: flex;
align-items: center;
justify-content: center;
text-align: center;
font-size: 12px;
transition: all 200ms;
.sidebar-anchor-item-link {
display: block;
width: 100%;
color: rgba(74, 89, 111, 0.6);
.sidebaricon {
display: block;
margin: 0 auto 6px;
font-size: 18px;
}
.sidebar-anchor-item-text {
display: block;
}
}
&:hover {
.sidebar-anchor-item-link {
color: #009cff;
}
}
&.active {
.sidebar-anchor-item-link {
color: #009cff;
}
&:hover {
.sidebar-anchor-item-link {
color: #009cff;
}
}
}
}
}
.main {
width: 100%;
height: 100%;
overflow: auto;
.page-container {
width: 100%;
height: 500px;
border-bottom: 1px solid pink;
}
}
</style>