入上图效果
通过判断几个id对应的dom离滚动区域上方的高度跟滚动区域高度对比高亮锚点
<template> <div v-loading="totalLoading" class="define-target-container"> <el-radio-group v-model="ucatsType" class="ucats-setting-content-group" size="medium" @change="changeRadio"> <el-radio-button :label="item.val" :key="i" v-for="(item, i) in radioOpts">{{ item.label }}</el-radio-button> </el-radio-group> <div class="define-target-middle-content"> <div class="left"> <template v-for="(item, i) in ucatsSetTabs[ucatsType]"> <DefineTargetComponents :key="`${item.id}_${i}`" :opt-config="item" :ucast-data="ucastJson[item.id]" v-loading="ucastLoading[`${item.id}Loading`]" @refreshScroll="getTabsAnchor" @refreshList="getApi" /> </template> </div> <ul class="right-anchor"> <li :key="i" v-for="(item, i) in ucatsSetTabs[ucatsType]"> <span :id="`${item.id}Link`" @click="jumpLink(item.id, `${item.id}Link`)">{{ item.title }}</span> </li> </ul> </div> </div> </template> <script> export default { name: "Maodian.vue", data() { }, mounted() { const dom = document.querySelector('.ucats-set-content') dom && dom.addEventListener('scroll', this.mouseScroll, true) }, beforeDestroy () { const dom = document.querySelector('.ucats-set-content') dom && dom.removeEventListener('scroll', this.mouseScroll, true) }, updated() { // 页面滚动锚点 this.getTabsAnchor() const { jumpId } = this.$route.params if (jumpId) { this.jumpLink(jumpId, `${jumpId}Link`) } else { // 默认第一个锚点选中 const spans = document.querySelectorAll('.right-anchor span') spans[0].style.color = '#296AFD' spans[0].parentNode.style.borderLeft = '1px solid #296AFD' } }, methods: { // 锚点跳转 jumpLink(id, linkId) { const spans = document.querySelectorAll('.right-anchor span') spans.forEach((item, index) => { spans[index].style.color = item.id === linkId ? '#296AFD' : '#111217' spans[index].parentNode.style.borderLeft = item.id === linkId ? '1px solid #296AFD' : '1px solid #DEE1E7' }) this.$nextTick(() => { document.querySelector('#' + id).scrollIntoView(true) }) }, mouseScroll () { const spans = document.querySelectorAll('.right-anchor span') // 锚点link const spanArr = Array.prototype.slice.call(spans) const scroll = document.querySelector('.ucats-set-content').scrollTop // 滚动的高度 const [top1, top2, top3] = this.offsetTops // 滚动的高度在第一个与下一个高度时,就显示对应的锚点link const conditionFirst = (scroll < top2) const conditionSecond = scroll >= top2 && (this.offsetTops.length === 3 ? (scroll < top3) : true) const conditionThird = scroll >= top3 if (conditionFirst) { this.scrollUp(spans, spanArr, 0) } else if (conditionSecond) { this.scrollUp(spans, spanArr, 1) } else if (conditionThird) { this.scrollUp(spans, spanArr, 2) } }, scrollUp (spans, arr, i) { arr.forEach((item, index) => { if (index !== i) { spans[index].style.color = '#111217' spans[index].parentNode.style.borderLeft = '1px solid #DEE1E7' } }) spans[i].style.color = '#296AFD' spans[i].parentNode.style.borderLeft = '1px solid #296AFD' }// 滚动监听end } } </script> <style scoped> .define-target-middle-content{ display: flex; padding-right: 16px; .left{ width: calc(100% - 160px); font-family: MicrosoftYaHei; font-size: 14px; line-height: 22px; /*height: 22px;*/ } .right-anchor{ width:160px; border-left: 1px solid #DEE1E7; position: fixed; right: 30px; li{ height: 32px; line-height: 32px; color: #111217; padding-left: 15px; cursor: pointer; } } } </style>