vue实现左右菜单联动实现
实现左右菜单联动的基本思路
左右菜单联动通常指左侧为分类菜单,右侧为内容区域,点击左侧菜单时右侧内容自动滚动到对应位置,反之滚动右侧时左侧菜单高亮对应项。核心在于通过监听滚动事件和点击事件实现双向绑定。
基于Vue3的代码实现
模板结构
<template>
<div class="container">
<div class="left-menu">
<div
v-for="(item, index) in menuList"
:key="index"
:class="{ 'active': activeIndex === index }"
@click="handleMenuClick(index, $event)"
>
{{ item.title }}
</div>
</div>
<div class="right-content" ref="contentRef" @scroll="handleContentScroll">
<div
v-for="(item, index) in menuList"
:key="index"
:ref="setContentRef"
class="content-section"
>
<h2>{{ item.title }}</h2>
<p>{{ item.content }}</p>
</div>
</div>
</div>
</template>
脚本部分
<script setup>
import { ref, onMounted } from 'vue'
const menuList = [
{ title: '分类1', content: '内容1...' },
{ title: '分类2', content: '内容2...' },
// 更多分类...
]
const activeIndex = ref(0)
const contentRef = ref(null)
const contentItems = ref([])
const setContentRef = (el) => {
if (el) contentItems.value.push(el)
}
const handleMenuClick = (index, event) => {
activeIndex.value = index
const targetEl = contentItems.value[index]
contentRef.value.scrollTo({
top: targetEl.offsetTop,
behavior: 'smooth'
})
}
const handleContentScroll = () => {
const scrollTop = contentRef.value.scrollTop
const scrollHeight = contentRef.value.scrollHeight
const clientHeight = contentRef.value.clientHeight
contentItems.value.forEach((item, index) => {
const itemTop = item.offsetTop
const itemBottom = itemTop + item.offsetHeight
if (scrollTop >= itemTop - 50 && scrollTop < itemBottom - 50) {
activeIndex.value = index
}
})
}
onMounted(() => {
// 初始化第一个菜单项高亮
activeIndex.value = 0
})
</script>
样式部分
<style scoped>
.container {
display: flex;
height: 100vh;
}
.left-menu {
width: 200px;
overflow-y: auto;
border-right: 1px solid #eee;
}
.left-menu div {
padding: 12px 16px;
cursor: pointer;
}
.left-menu div.active {
background-color: #1890ff;
color: white;
}
.right-content {
flex: 1;
overflow-y: auto;
padding: 20px;
}
.content-section {
margin-bottom: 40px;
min-height: 300px;
}
</style>
实现关键点说明
双向绑定机制
通过handleMenuClick处理左侧菜单点击,使用scrollTo方法平滑滚动到对应内容区域。通过handleContentScroll监听右侧滚动事件,计算当前可视区域对应的内容块并更新左侧菜单高亮状态。

性能优化
滚动事件使用防抖处理避免频繁触发,示例中未展示但实际项目建议添加:
import { debounce } from 'lodash-es'
const handleContentScroll = debounce(() => { ... }, 100)
动态内容处理
使用setContentRef收集所有内容块的DOM引用,确保能准确计算各内容块位置。当内容动态加载时需清空contentItems重新收集。

扩展功能建议
锚点导航
可在URL哈希中记录当前激活的菜单项,实现浏览器前进后退导航:
watch(activeIndex, (val) => {
window.location.hash = `#${menuList[val].title}`
})
响应式设计
通过媒体查询在小屏幕下转换为上下布局:
@media (max-width: 768px) {
.container { flex-direction: column; }
.left-menu { width: 100%; height: 60px; }
}






