1 前言
1.1 功能
- 动态渲染多级嵌套菜单
- 点击菜单跳转页面
- 子菜单高亮,对应父级菜单也高亮
- 不同路由高亮同一菜单
1.2源码
2 sub-menu 组件
<template>
<el-sub-menu :index="menu.name" v-if="menu.childMenu">
<template #title>
<el-icon><Menu /></el-icon>
<span>{{ menu.chineseName }}</span>
</template>
<!-- 多级嵌套菜单渲染 -->
<sub-menu :menu="menuItem" v-for="menuItem in menu.childMenu" :key="menuItem.name"></sub-menu>
</el-sub-menu>
<el-menu-item :index="menu.name" v-else>
<el-icon><Menu /></el-icon>
<template #title>{{ menu.chineseName }}</template>
</el-menu-item>
</template>
<script setup lang="ts">
interface Menu {
name: string //菜单唯一标识,与路由名保持一致
chineseName: string //菜单显示名称
childMenu?: Menu[] | undefined //子菜单
}
defineProps<{
menu: Menu
}>()
</script>
3 menu 组件
<template>
<el-menu :default-active="defaultActive" router>
<sub-menu :menu="menu" v-for="menu in menuList" :key="menu.name"></sub-menu>
</el-menu>
</template>
<script setup lang="ts">
import { computed } from 'vue'
import { useRoute } from 'vue-router'
import SubMenu from './subMenu.vue'
// useRoute().meta?.parentMenu : 自定义路由点亮菜单,在路由的 meta 上配置 parentMenu 字段,值为父级菜单的 name 值
const defaultActive = computed(() => useRoute().meta?.parentMenu || useRoute().name)
const menuList = [
{
name: 'home',
chineseName: '首页'
},
{
name: 'literature',
chineseName: '文学',
childMenu: [
{
name: 'cartoon',
chineseName: '动漫',
},
{
name: 'essay',
chineseName: '散文随笔',
childMenu: [
{
name: 'youth_literature',
chineseName: '青春文学',
}
]
},
{
name: 'suspenseful_reasoning',
chineseName: '悬疑推理',
childMenu: [
{
name: 'history',
chineseName: '历史',
},
{
name: 'noval',
chineseName: '小说',
childMenu: [
{
name: 'fiction',
chineseName: '科幻',
},
{
name: 'martial_arts',
chineseName: '武侠',
}
]
}
]
}
]
},
{
name: 'psychology',
chineseName: '心理学',
}
]
</script>
<style lang="scss" scoped>
// 子菜单高亮,对应父级菜单也高亮
.el-menu ::v-deep(.el-sub-menu.is-active > .el-sub-menu__title) {
color: var(--el-color-primary);
}
</style>