VUE篇之,实现锚点定位,滚动与导航联动
实现效果:点击侧边栏,右侧内容能够自动滑动到显示区域
滚动显示区域,侧边栏能够跟随高亮
代码如下:
<template><div class="root"><div class="slidebar"><ul class="sidebar-anchor-list"><liclass="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>