1. 创建路由时将路由信息对象进行抽离
将路由信息对象单独抽离到router/routes.ts
文件
关键:利用路由元信息meta
,定义3个属性
- hidden:控制当前路由是否显示在菜单栏中
- title:菜单拦名称
- icon:对应菜单名称前面的图标
//对外暴露配置路由(常量路由)
export const constantRout = [
{
path: '/screen',
component: () => import('@/views/screen/index.vue'),
name: 'Screen',
meta: {
hidden: false,
title: '数据大屏',
icon: 'Platform',
},
},
{
path: '/acl',
component: () => import('@/layout/index.vue'),
name: 'Acl',
meta: {
hidden: false,
title: '权限管理',
icon: 'Lock',
},
children: [
{
path: '/acl/user',
component: () => import('@/views/acl/user/index.vue'),
name: 'User',
meta: {
hidden: false,
title: '用户管理',
icon: 'User',
},
},
{
path: '/acl/role',
component: () => import('@/views/acl/role/index.vue'),
name: 'Role',
meta: {
hidden: false,
title: '角色管理',
icon: 'UserFilled',
},
},
{
path: '/acl/permission',
component: () => import('@/views/acl/permission/index.vue'),
name: 'Permission',
meta: {
hidden: false,
title: '菜单管理',
icon: 'Monitor',
},
},
],
},
]
在router/index.ts
文件引入router.ts
文件
import { createRouter, createWebHashHistory } from 'vue-router'
import { constantRoute } from './routes'
//创建路由器
const router = createRouter({
//路由模式hash
history: createWebHashHistory(),
routes: constantRoute,
//滚动行为
scrollBehavior() {
return {
left: 0,
top: 0,
}
},
})
export default router
2. 将路由信息对象挂载到pinia仓库中
将路由信息对象挂载到pinia仓库中,是为了数据共享,供组件使用
//引入路由(常量路由)
import { constantRoute } from '../../router/routes'
const useUserStore = defineStore('User', {
state: (): userState => {
return {
token: GET_TOKEN(),
// 存储路由信息用来遍历生成菜单结构
menuRoutes: constantRoute, //仓库存储生成菜单需要数组(路由)
}
},
}
完成将路由信息挂载到pinia仓库中
3. 在组件中通过路由信息对象渲染菜单
Menu
是封装的组件,接收父组件传递的userStore.menuRoutes
也就是存放在pinia仓库中的路由信息对象
<!-- 展示菜单区域 -->
<el-scrollbar class="scrllbar">
<el-menu background-color="#001529" text-color="white">
<!-- 根据路由动态生成菜单 -->
<Menu :menuList="userStore.menuRoutes"></Menu>
</el-menu>
</el-scrollbar>
在子组件Menu
中声明接收:
//通过props接收父组件传递的路由组件信息
defineProps(['menuList'])
Menu
组件完整写法:
思路:通过路由信息对象中的children
属性判断是否有子路由,如果有子路由,则继续判断子路由的个数,从而进行对应的判断处理
<template>
<!-- 根据路由来遍历左侧菜单展示信息 -->
<template v-for="(item, index) in menuList" :key="item.path">
<!-- 没有子路由 -->
<template v-if="!item.children">
<el-menu-item
v-if="!item.meta.hidden"
:index="item.path"
@click="goRoute"
>
<template #title>
<el-icon>
<component :is="item.meta.icon"></component>
</el-icon>
<span>{{ item.meta.title }}</span>
</template>
</el-menu-item>
</template>
<!-- 有子路由但是只有一个 -->
<template v-else-if="item.children && item.children.length == 1">
<el-menu-item
v-if="!item.children[0].meta.hidden"
:index="item.children[0].path"
@click="goRoute"
>
<template #title>
<el-icon>
<component :is="item.children[0].meta.icon"></component>
</el-icon>
<span>{{ item.children[0].meta.title }}</span>
</template>
</el-menu-item>
</template>
<!-- 有子路由且个数大于一个 -->
<template v-if="item.children && item.children.length > 1">
<el-sub-menu :index="item.path">
<template #title>
<el-icon>
<component :is="item.meta.icon"></component>
</el-icon>
<span>{{ item.meta.title }}</span>
</template>
<Menu :menuList="item.children"></Menu>
</el-sub-menu>
</template>
</template>
</template>
<script setup lang="ts">
import { useRouter } from 'vue-router'
//通过props接收父组件传递的路由组件信息
defineProps(['menuList'])
let $router = useRouter()
const goRoute = (vc: any) => {
//路由跳转
$router.push(vc.index)
}
</script>
<script lang="ts">
// 当子路由个数大于等于一个时,并且或许子路由还有后代路由时。
// 这里我们使用了递归组件。递归组件需要命名(另外使用一个script标签,vue2格式)。
export default {
name: 'Menu',
}
</script>
<style scoped lang="scss">
</style>
注意:在Menu
组件中使用了Menu
(递归组件),递归组件需要命名(另外使用一个script标签,vue2格式)。
export default {
name: 'Menu',
}
注意:在el-menu-item
组件中有一个click
方法,对应一个函数,由element
提供,会接收一个组件实例参数,并配合useRouter
进行路由跳转
const goRoute = (vc: any) => {
//路由跳转
$router.push(vc.index)
}