vue实现导航联动
实现导航联动的基本思路
导航联动通常指在页面滚动时,导航菜单高亮显示当前可见区域的对应项,或点击导航菜单时页面滚动到对应区域。Vue中可通过监听滚动事件或使用第三方库实现。
监听滚动事件实现联动
通过window.addEventListener监听滚动事件,结合Element.getBoundingClientRect()判断当前视口位置与各区块的关系,动态更新导航高亮状态。
<template>
<div>
<nav>
<ul>
<li v-for="(item, index) in sections" :key="index"
:class="{ active: currentIndex === index }"
@click="scrollTo(index)">
{{ item.title }}
</li>
</ul>
</nav>
<section v-for="(item, index) in sections" :key="index" :ref="`section-${index}`">
<h2>{{ item.title }}</h2>
<p>{{ item.content }}</p>
</section>
</div>
</template>
<script>
export default {
data() {
return {
sections: [
{ title: 'Section 1', content: '...' },
{ title: 'Section 2', content: '...' },
{ title: 'Section 3', content: '...' }
],
currentIndex: 0
}
},
mounted() {
window.addEventListener('scroll', this.handleScroll)
},
beforeDestroy() {
window.removeEventListener('scroll', this.handleScroll)
},
methods: {
handleScroll() {
const scrollPosition = window.scrollY
this.sections.forEach((_, index) => {
const el = this.$refs[`section-${index}`][0]
if (el) {
const { top, bottom } = el.getBoundingClientRect()
if (top <= 100 && bottom >= 100) {
this.currentIndex = index
}
}
})
},
scrollTo(index) {
const el = this.$refs[`section-${index}`][0]
if (el) {
window.scrollTo({
top: el.offsetTop,
behavior: 'smooth'
})
}
}
}
}
</script>
<style>
.active {
color: red;
font-weight: bold;
}
</style>
使用vue-scrollto插件简化实现
安装vue-scrollto插件可快速实现平滑滚动和导航联动功能:
npm install vue-scrollto
配置插件后直接调用方法:
<template>
<div>
<nav>
<ul>
<li v-for="(item, index) in sections" :key="index"
:class="{ active: currentIndex === index }"
@click="$scrollTo(`#section-${index}`)">
{{ item.title }}
</li>
</ul>
</nav>
<section v-for="(item, index) in sections" :key="index" :id="`section-${index}`">
<h2>{{ item.title }}</h2>
<p>{{ item.content }}</p>
</section>
</div>
</template>
<script>
import VueScrollTo from 'vue-scrollto'
export default {
data() {
return {
sections: [
{ title: 'Section 1', content: '...' },
{ title: 'Section 2', content: '...' },
{ title: 'Section 3', content: '...' }
],
currentIndex: 0
}
},
mounted() {
window.addEventListener('scroll', this.handleScroll)
},
methods: {
handleScroll() {
const scrollPosition = window.scrollY
this.sections.forEach((_, index) => {
const el = document.getElementById(`section-${index}`)
if (el) {
const { top, bottom } = el.getBoundingClientRect()
if (top <= 100 && bottom >= 100) {
this.currentIndex = index
}
}
})
}
}
}
</script>
性能优化建议
滚动事件可能频繁触发,需要添加节流函数控制执行频率:
methods: {
handleScroll: _.throttle(function() {
// 原有逻辑
}, 100)
}
使用Intersection Observer API替代滚动事件监听,更适合现代浏览器:
mounted() {
const observer = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
const index = this.sections.findIndex(
(_, i) => entry.target.id === `section-${i}`
)
if (index !== -1) this.currentIndex = index
}
})
}, { threshold: 0.5 })
this.sections.forEach((_, index) => {
const el = document.getElementById(`section-${index}`)
if (el) observer.observe(el)
})
}






