vue楼层导航怎么实现
Vue 楼层导航实现方法
监听滚动事件与计算当前楼层
通过 window.addEventListener 监听滚动事件,结合 getBoundingClientRect() 计算各楼层容器的位置。使用 Vue 的 ref 获取 DOM 节点,动态判断当前视口所在的楼层区域。
data() {
return {
currentFloor: 0,
floors: [] // 存储各楼层DOM节点
}
},
mounted() {
this.floors = this.$refs.floor.map(item => item.$el);
window.addEventListener('scroll', this.handleScroll);
},
methods: {
handleScroll() {
const scrollPosition = window.scrollY;
this.floors.forEach((floor, index) => {
const top = floor.offsetTop;
const height = floor.offsetHeight;
if (scrollPosition >= top && scrollPosition < top + height) {
this.currentFloor = index;
}
});
}
}
导航菜单高亮联动
导航菜单使用 v-for 渲染,通过 :class 动态绑定高亮样式。currentFloor 变化时自动更新激活状态。

<div class="nav">
<div
v-for="(item, index) in navItems"
:key="index"
:class="{ active: currentFloor === index }"
@click="scrollToFloor(index)">
{{ item.name }}
</div>
</div>
平滑滚动到指定楼层
通过 scrollTo 或第三方库(如 smooth-scroll)实现点击导航时的平滑滚动效果。计算目标楼层的 offsetTop 并设置滚动行为。

scrollToFloor(index) {
const target = this.floors[index];
window.scrollTo({
top: target.offsetTop,
behavior: 'smooth'
});
}
性能优化建议
使用防抖函数(如 lodash.debounce)减少滚动事件触发频率。组件销毁时移除事件监听,避免内存泄漏。
import { debounce } from 'lodash';
created() {
this.debouncedScroll = debounce(this.handleScroll, 100);
},
beforeDestroy() {
window.removeEventListener('scroll', this.debouncedScroll);
}
完整组件示例
以下是一个整合后的组件代码示例:
<template>
<div>
<div class="nav">
<div
v-for="(item, index) in navItems"
:key="index"
:class="{ active: currentFloor === index }"
@click="scrollToFloor(index)">
{{ item.name }}
</div>
</div>
<div v-for="(item, index) in floorsData" :key="index" ref="floor">
<h3>{{ item.title }}</h3>
<p>{{ item.content }}</p>
</div>
</div>
</template>
<script>
import { debounce } from 'lodash';
export default {
data() {
return {
currentFloor: 0,
floors: [],
navItems: [
{ name: '楼层1' },
{ name: '楼层2' }
],
floorsData: [
{ title: '楼层1标题', content: '...' },
{ title: '楼层2标题', content: '...' }
]
};
},
mounted() {
this.floors = this.$refs.floor;
window.addEventListener('scroll', this.debouncedScroll);
},
created() {
this.debouncedScroll = debounce(this.handleScroll, 100);
},
methods: {
handleScroll() {
const scrollPosition = window.scrollY;
this.floors.forEach((floor, index) => {
const top = floor.offsetTop;
const height = floor.offsetHeight;
if (scrollPosition >= top && scrollPosition < top + height) {
this.currentFloor = index;
}
});
},
scrollToFloor(index) {
const target = this.floors[index];
window.scrollTo({
top: target.offsetTop,
behavior: 'smooth'
});
}
},
beforeDestroy() {
window.removeEventListener('scroll', this.debouncedScroll);
}
};
</script>
<style>
.nav {
position: fixed;
right: 20px;
top: 50%;
transform: translateY(-50%);
}
.nav div {
padding: 10px;
cursor: pointer;
}
.nav div.active {
color: red;
font-weight: bold;
}
</style>






