前文回顾
视图创建约定
视图目录结构
本文针对二级菜单项进行讲解。
主页不需要用目录包裹,父菜单项目录只需要创建一个 page.ts
配置文件,里面的子目录是子菜单项。
菜单项配置
主页配置示例
export default {
title: '主页',
menuItem: {
icon: 'home-filled'
}
}
父菜单项配置示例
export default {
title: '学习园地',
menuItem: {
icon: 'reading',
isParent: true
}
}
子菜单项配置示例
export default {
title: '资源导航',
menuItem: {
icon: 'link'
}
}
router/index.ts
路由、菜单项映射获取
// 调整路由的层级顺序,使父菜单项一定在子菜单项上面
routes.sort(function (a, b) {
return a.name.localeCompare(b.name)
})
const routeMap: Map<string, RouteRecordRaw> = new Map()
const menuItemMap: Map<string, any> = new Map()
routes.forEach((route: any) => {
// 父菜单项不设置 component(仅有一个文件夹和 page.ts),所以不让它加到路由里面
if (route.component) {
const title = route.meta.title
routeMap.set(title, route)
}
if (route.meta.menuItem) {
const name = route.name
const path = route.path
const icon = route.meta.menuItem.icon
const title = route.meta.title
const isParent = route.meta.menuItem.isParent
if (isParent) {
menuItemMap.set(name, {
icon,
title,
childrens: []
})
} else {
const parent = path.split('/')[1]
// 如果存在这个父菜单项
if (menuItemMap.has(parent)) {
menuItemMap.get(parent).childrens.push({
path,
icon,
title
})
} else {
menuItemMap.set(name, {
path,
icon,
title
})
}
}
}
})
导出菜单项数组
export const getMenuItems = () => {
return Array.from(menuItemMap.values())
}
菜单项渲染组件
关于 el-menu 的菜单项高亮设置请移步:【Vue3+Pinia+Element Plus】el-menu :default-active 当前菜单项保持激活。
<template>
<el-menu mode="horizontal" :ellipsis="false" router menu-trigger="click" unique-opened :default-active="elMenuActive">
<template v-for="(item, idx) in menuItems">
<template v-if="!item.childrens">
<el-menu-item :index="item.path" :key="idx">
<el-icon>
<component :is="item.icon"></component>
</el-icon>
<span>{{ item.title }}</span>
</el-menu-item>
</template>
<template v-else>
<el-sub-menu :index="idx" :key="idx">
<template #title>
<el-icon>
<component :is="item.icon"></component>
</el-icon>
<span>{{ item.title }}</span>
</template>
<el-menu-item v-for="(item2, idx2) in item.childrens" :key="idx2" :index="item2.path">
<el-icon>
<component :is="item2.icon"></component>
</el-icon>
<span>{{ item2.title }}</span>
</el-menu-item>
</el-sub-menu>
</template>
</template>
</el-menu>
</template>
<script setup lang="ts">
import { getMenuItems } from '@/router'
const menuItems = getMenuItems()
</script>
效果图
参考资料
[1] 老张前端. vue3动态组件[Z/OL]. https://www.bilibili.com/video/BV1Ju4y1H7Ri. 2023.