记住 一级(el-sub-menu)的都是只是展示的 点击跳转的都是一级下的子级(el-menu-item)
完整展示
1:在登陆功能进行登陆 获取menu列表
注册路由表的时候 把文件进行创建好 因为注册的方法需要获取这个路径
整个router下的main product等等都要创建
//1:发送你的用户名和密码获取token和用户信息**
//2:拿着token获取菜单列表接口 (我的项目封装的axios ,这里演示的话就写这么个意思 知道就行)**
const userMenuData=await axios.get('xxxx'{'token':'xxxxx'})
//3:保存在 vuex中
//4:把菜单权限注入到路由表内
const mapMenusToRouters=(userMenus: any[])=> {
console.log(userMenus, 'userMenus')
// type==1说明有二级 type==2 就是二级
// 保存处理好的路由。
const routes: RouteRecordRaw[] = [];
// 获取所有的路由文件
const allRoutes: RouteRecordRaw[] = [];
// 1先查询路由目录文件 获取main下的ts文件
const routeFiles = require.context('../router/main', true, /\.ts/)
// 2 获取keys() 引入文件
routeFiles.keys().forEach(key => {
// 3切割文件./ .ts
const route = require('../router/main' + key.split('.')[1])
// 4 把文件追加到数组 allRoutes中
allRoutes.push(route.default)
});
const _recurseGetRoute = (menus: any[]) => {
for (const menu of menus) {
if (menu.type == 1) {
_recurseGetRoute(menu.children ?? [])
} else {
// type==2 没有了子集
const route = allRoutes.find((route) => {
return route.path == menu.url
})
if (route) {
routes.push(route)
}
}
}
}
_recurseGetRoute(userMenus)
if (routes) {
return routes
} else {
return []
}
}
//记得 import {useStore} from 'store';
const store = useStore();
const userMenu = computed(() => {
return store.state.login.userMenus;
});
//调用函数进行处理
const routes = mapMenusToRouters(userMenus)
//放在router.ts的main 下的children中=========>路由表注册完毕
routes.forEach((key: RouteRecordRaw) => router.addRoute('main', key) )
2:侧边菜单界面
<template>
<div class="nav-menu">
<div class="logo">
<img class="img" src="~@/assets/img/logo.svg" alt="logo" />
<span class="title" >vue3+ts</span>
</div>
<el-menu
:default-active="dafaultValue"
background-color="#0c2135"
text-color="#b7bdc3"
:collapse="isCollapse"
active-text-color="#0a60bd"
class="el-menu-vertical"
>
<template v-for="item in userMenu" :key="item.id">
<template v-if="item.type == 1">
<el-sub-menu :index="item.id + ''">
<template #title>
<el-icon><Platform /></el-icon>
<span>{{ item.name }}</span>
</template>
<template v-for="subItem in item.children" :key="subItem.id">
<el-menu-item
:index="subItem.id + ''"
@click="handleMenuItemClick(subItem)"
>
<template #title>
<el-icon><Platform /></el-icon>
<span>{{ subItem.name }}</span>
</template>
</el-menu-item>
</template>
</el-sub-menu>
</template>
<template v-else-if="item.type === 2">
<el-menu-item :index="item.id + ''">
<span>{{ item.name }}</span>
</el-menu-item>
</template>
</template>
</el-menu>
</div>
</template>
<script setup lang="ts">
import { useRouter, useRoute } from "vue-router";
import { useStore } from "@/store/index";
//1:vuex获取菜单列表
const store = useStore();
const userMenu = computed(() => {
return store.state.login.userMenus;
});
//2:点击el-menu-item上的按钮跳转的函数
const router = useRouter();
const handleMenuItemClick = (item: any) => {
// item.url不存在就跳转到自己定义的界面 比如404 (/not-found)
router.push({ path: item.url ?? "/not-found" });
};
//3: el-sub-menu上有一个属性是dafaultValue
// 意思是默认选择的路由菜单 不能写死 不然我刷新的时候 就不能显示当前的选中菜单,而是选中写死的菜单
// 比如 我写死的dafaultValue是用户管理,当前点击菜单管理进行刷新数据的时候 他会跑到用户管理里面 这是错误的
const pathMapToMenus = (userMenu: any[], currentPath: string): any => {
for (const menu of userMenu) {
// 如果type==1 那么就是含有二级
if (menu.type == 1) {
console.log(menu)
// 调用函数本身 把结果返回给我
const findMenu = pathMapToMenu(menu.children ?? [], currentPath)
if (findMenu) {
return findMenu
}
// 如果type==2 那么直接判断后把结果返回给我
} else if (menu.type == 2 && currentPath == menu.url) {
console.log(menu, '2')
return menu
}
}
}
const route = useRoute();
const currentPath = route.path;
const menu = pathMapToMenu(userMenu.value, currentPath);
const dafaultValue = ref(menu.id + "");
</script>
以上把侧边菜单展示实现了,, 但是实现跳转的话 路由表必须有相对应的路由
router/index.ts
import { createRouter, createWebHashHistory, RouteRecordRaw } from 'vue-router'
import { accountLoginRequest, RequestUserInfoByid, RequestUserMenusByRoleId } from '@/service/login/login';
const routes: Array<RouteRecordRaw> = [
{
path: '/',
redirect: '/main'
},
{
path: '/login',
name: 'login',
component: () => import(/* webpackChunkName: "about" */ '../views/login/login.vue')
},
{
path: '/main',
name: 'main',
redirect:'/main/system/user',
component: () => import(/* webpackChunkName: "about" */ '../views/main/main.vue'),
children:[]
},
{
//404请求不存在的路径
path: '/:pathMatch(.*)*',
component: () => import('@/views/not-found/not-found.vue')
}
]
const router = createRouter({
history: createWebHashHistory(),
routes
})
// 导航守卫
router.beforeEach((to) => {
if (to.path !== '/login') {
const token = window.localStorage.getItem('token')
if (!token) {
return '/login'
}
}
})
console.log(router, 'router')
export default router