做网站的时候,菜单导航几乎是每个项目都绕不开的部分。特别是在用 Vue 开发单页应用时,一个结构清晰、样式灵活的菜单导航组件能让整个页面看起来更专业,也方便用户操作。比如你做个后台管理系统,左边侧边栏一堆功能入口,用 Vue 来组织这些菜单项就特别顺手。
从最简单的结构开始
先不考虑复杂逻辑,只搭一个基础的横向菜单。HTML 结构可以用 ul 和 li 来写,再通过 Vue 控制点击切换当前激活项。
<template>
<nav class="nav-menu">
<ul>
<li
v-for="(item, index) in menuItems"
:key="index"
:class="{ active: activeIndex === index }"
@click="handleClick(index)"
>
{{ item.label }}
</li>
</ul>
</nav>
</template>
<script>
export default {
data() {
return {
activeIndex: 0,
menuItems: [
{ label: '首页' },
{ label: '关于' },
{ label: '服务' },
{ label: '联系' }
]
};
},
methods: {
handleClick(index) {
this.activeIndex = index;
}
}
};
</script>
<style scoped>
.nav-menu ul {
display: flex;
list-style: none;
padding: 0;
margin: 0;
}
.nav-menu li {
padding: 12px 20px;
cursor: pointer;
}
.nav-menu li.active {
background-color: #007bff;
color: white;
border-radius: 4px;
}
</style>
支持多级嵌套的侧边栏
实际开发中,菜单往往不止一层。比如后台常见的“用户管理”下面还有“列表”“添加”等子项。这时候可以把数据结构改成嵌套形式,通过递归组件来渲染。
先定义带 children 的菜单数据:
menuItems: [
{
label: '仪表盘',
path: '/dashboard'
},
{
label: '用户管理',
children: [
{ label: '用户列表', path: '/users' },
{ label: '新增用户', path: '/users/add' }
]
}
]
然后创建一个递归组件 SidebarItem.vue:
<template>
<div class="sidebar-item">
<div
v-if="!item.children"
class="menu-link"
@click="$router.push(item.path)"
>
{{ item.label }}
</div>
<div v-else>
<div class="menu-parent" @click="isExpanded = !isExpanded">
{{ item.label }}
<span>{{ isExpanded ? '▼' : '▶' }}</span>
</div>
<transition name="slide">
<div v-show="isExpanded" class="submenu">
<SidebarItem
v-for="child in item.children"
:key="child.path"
:item="child"
/>
</div>
</transition>
</div>
</div>
</template>
<script>
export default {
name: 'SidebarItem',
props: ['item'],
data() {
return {
isExpanded: false
};
}
};
</script>
结合 Vue Router 实现高亮
在真实项目里,菜单通常和路由联动。当进入某个页面时,对应的菜单项自动变色或加粗。利用 Vue Router 提供的 $route 对象就能轻松实现。
比如判断当前路径是否匹配:
:class="[$style.menuItem, {
[$style.active]: item.path === $route.path
}]"
或者更灵活一点,判断是否是父级路径:
computed: {
isActive() {
const currentPath = this.$route.path;
return currentPath.startsWith(this.item.path);
}
}
这样进到 /users/123 编辑页时,“用户列表”那一项依然能保持高亮状态,用户体验会更好。
小细节优化
加个折叠图标、过渡动画、键盘上下键切换选中项,这些小改进会让组件更顺滑。比如给展开收起加上 CSS 过渡:
.slide-enter-active, .slide-leave-active {
transition: height 0.3s ease;
}
.slide-enter-to {
height: auto;
}
.slide-enter, .slide-leave-to {
height: 0;
overflow: hidden;
}
平时自己搭项目,这种导航组件写一次之后可以直接复制粘贴复用。时间一长,慢慢就攒出一套自己的组件库了,效率提升很明显。