vue实现菜单
使用 Vue 实现菜单
Vue 可以轻松实现动态菜单,通常结合路由和组件化思想。以下是一个基于 Vue 3 和 Vue Router 的菜单实现方案:
基础菜单结构
在 Vue 中,菜单通常是一个递归组件,能够处理多级嵌套。创建一个 Menu.vue 组件:
<template>
<ul>
<li v-for="item in menuItems" :key="item.path">
<router-link v-if="!item.children" :to="item.path">
{{ item.title }}
</router-link>
<template v-else>
<span>{{ item.title }}</span>
<Menu :menu-items="item.children" />
</template>
</li>
</ul>
</template>
<script>
export default {
name: 'Menu',
props: {
menuItems: {
type: Array,
required: true
}
}
}
</script>
路由配置
在路由配置中定义菜单结构:
const routes = [
{
path: '/',
name: 'Home',
component: Home,
meta: { title: '首页' }
},
{
path: '/products',
name: 'Products',
component: Products,
meta: { title: '产品' },
children: [
{
path: 'list',
name: 'ProductList',
component: ProductList,
meta: { title: '产品列表' }
}
]
}
]
动态生成菜单
从路由配置中提取菜单项:

function generateMenuItems(routes) {
return routes.map(route => {
const item = {
path: route.path,
title: route.meta?.title || route.name
}
if (route.children) {
item.children = generateMenuItems(route.children)
}
return item
})
}
状态管理
对于需要根据权限动态变化的菜单,可以使用 Pinia 或 Vuex 管理菜单状态:
// stores/menu.js
import { defineStore } from 'pinia'
export const useMenuStore = defineStore('menu', {
state: () => ({
menuItems: []
}),
actions: {
async fetchMenu() {
const response = await fetch('/api/menu')
this.menuItems = await response.json()
}
}
})
响应式菜单
添加响应式特性,在小屏幕设备上显示汉堡菜单:

<template>
<button @click="toggleMenu">☰</button>
<nav :class="{ 'menu-visible': isMenuVisible }">
<Menu :menu-items="menuItems" />
</nav>
</template>
<script>
import { ref } from 'vue'
import Menu from './Menu.vue'
export default {
components: { Menu },
setup() {
const isMenuVisible = ref(false)
const toggleMenu = () => {
isMenuVisible.value = !isMenuVisible.value
}
return { isMenuVisible, toggleMenu }
}
}
</script>
<style>
.menu-visible {
display: block;
}
</style>
权限控制
实现基于角色的菜单过滤:
function filterMenuByRole(menuItems, userRole) {
return menuItems.filter(item => {
if (item.roles && !item.roles.includes(userRole)) {
return false
}
if (item.children) {
item.children = filterMenuByRole(item.children, userRole)
}
return true
})
}
动画效果
为菜单添加过渡动画:
<template>
<Transition name="slide">
<nav v-if="isMenuVisible">
<Menu :menu-items="menuItems" />
</nav>
</Transition>
</template>
<style>
.slide-enter-active, .slide-leave-active {
transition: transform 0.3s ease;
}
.slide-enter-from, .slide-leave-to {
transform: translateX(-100%);
}
</style>
完整实现示例
将上述各部分组合起来,创建一个完整的菜单系统:
- 定义路由配置
- 创建可递归的菜单组件
- 添加状态管理
- 实现响应式布局
- 加入权限控制
- 添加动画效果
这种实现方式灵活可扩展,能够适应各种复杂菜单需求。






