vue实现左侧楼层导航
Vue 实现左侧楼层导航
基本实现思路
- 使用 Vue 的响应式特性监听滚动位置
- 根据滚动位置高亮对应的导航项
- 点击导航项平滑滚动到对应区域
核心代码实现
<template>
<div class="container">
<div class="content">
<div
v-for="(item, index) in sections"
:key="index"
:id="'section-'+index"
class="section"
>
<h2>{{ item.title }}</h2>
<p>{{ item.content }}</p>
</div>
</div>
<div class="nav">
<ul>
<li
v-for="(item, index) in sections"
:key="index"
:class="{active: activeIndex === index}"
@click="scrollTo(index)"
>
{{ item.title }}
</li>
</ul>
</div>
</div>
</template>
<script>
export default {
data() {
return {
sections: [
{title: 'Section 1', content: '...'},
{title: 'Section 2', content: '...'},
{title: 'Section 3', content: '...'}
],
activeIndex: 0
}
},
mounted() {
window.addEventListener('scroll', this.handleScroll)
},
beforeDestroy() {
window.removeEventListener('scroll', this.handleScroll)
},
methods: {
handleScroll() {
const sections = document.querySelectorAll('.section')
sections.forEach((section, index) => {
const rect = section.getBoundingClientRect()
if(rect.top <= 100 && rect.bottom >= 100) {
this.activeIndex = index
}
})
},
scrollTo(index) {
const element = document.getElementById(`section-${index}`)
element.scrollIntoView({behavior: 'smooth'})
}
}
}
</script>
<style>
.container {
display: flex;
}
.content {
flex: 1;
}
.nav {
width: 200px;
position: fixed;
}
.nav li {
cursor: pointer;
padding: 8px;
}
.nav li.active {
color: #42b983;
font-weight: bold;
}
.section {
min-height: 500px;
padding: 20px;
border-bottom: 1px solid #eee;
}
</style>
优化方案
-
添加节流函数优化滚动性能
throttle(func, delay) { let timer = null return function() { if(!timer) { timer = setTimeout(() => { func.apply(this, arguments) timer = null }, delay) } } } -
使用 IntersectionObserver API 替代滚动监听
initObserver() { const options = { root: null, rootMargin: '0px', threshold: 0.5 }
this.observer = new IntersectionObserver((entries) => { entries.forEach(entry => { if(entry.isIntersecting) { const id = entry.target.id this.activeIndex = parseInt(id.split('-')[1]) } }) }, options)
document.querySelectorAll('.section').forEach(section => { this.observer.observe(section) }) }

3. 添加平滑滚动动画
```javascript
scrollTo(index) {
const element = document.getElementById(`section-${index}`)
const start = window.pageYOffset
const target = element.offsetTop
const distance = target - start
const duration = 500
let startTime = null
function animation(currentTime) {
if(!startTime) startTime = currentTime
const timeElapsed = currentTime - startTime
const run = ease(timeElapsed, start, distance, duration)
window.scrollTo(0, run)
if(timeElapsed < duration) requestAnimationFrame(animation)
}
function ease(t, b, c, d) {
t /= d/2
if(t < 1) return c/2*t*t + b
t--
return -c/2 * (t*(t-2) - 1) + b
}
requestAnimationFrame(animation)
}
注意事项
- 确保导航栏使用固定定位(position: fixed)
- 每个内容区块需要有足够的高度和明显的分隔
- 移动端需要考虑触摸事件和响应式布局
- 对于动态加载的内容,需要在内容更新后重新计算位置






