vue3 动态添加路由并生成左侧菜单栏
先说下思路,登录后跳转到基础页面,
每访问一个页面时,会进到路由守卫的方法
守卫进行身份验证,登录成功后才能跳转到静态路由外的页面,否则就重定向回login页面
登录后跳转到基础页面(因为基础页面包含了左侧菜单栏,获取路由后可以更新菜单栏)。先判断是否已经有路由,防止每次进入守卫方法时重复获取路由,最后重定向到登录后的首页
一、创建静态路由,也就是登录页面和基础页面
登录后的页面是base,base里面包含了左侧菜单栏
import { createRouter, createWebHistory } from 'vue-router'
const routes = [
{
path: '/base',
name: 'Base',
component: () => import("../views/base/BaseView.vue"),
children: [],
},
{
path: '/login',
name: 'login',
hidden: true,
component: () => import('../views/Login.vue'),
meta: {
requireAuth: false // 是否需要身份验证
}
}
]
const router = createRouter({
history: createWebHistory(),
routes
});
export default router
二、在守卫方法中进行更新路由
我的路由信息只贴了3条,有一级的也有二级的。给大家做个参考
循环拿到路由信息,判断是一级还是二级,一级目录要新增children空数组,不然二级添加不进去
// 添加全局前置守卫
router.beforeEach((to, from, next) => {
var requireAuth = true
const token = localStorage.getItem('accessToken')
let newT = router.options.routes[0];/* 需要在里面动态添加子路由的一个根组,插入的也是这个根组对象 */
if (null != to.meta.requireAuth) {
requireAuth = to.meta.requireAuth
}
if (requireAuth && !token) {
next('/login')
} else {
if (to.path != "/login" && to.path != "/") {
if (newT.children.length == 0) {//条件保护,防止全局路由守卫死循环执行。
//返过来的路由信息
const data = [
{
id: 1,
parentId: 0,
path: "/terminalList",
name: "首页",
hidden: false,
component: "/terminal/TerminalList",
},
{
id: 2,
parentId: 0,
path: "/one",
name: "一级目录",
hidden: false,
component: "/base/RightView",
},
{
id: 3,
parentId: 2,
path: "/terminalSearch",
name: "1",
hidden: false,
component: "/search/TerminalSearch",
},
]
for (let i = 0; i < data.length; i++) {
if (data[i].parentId === 0) {
newT.children.push(
{
id: data[i].id,
parentId: data[i].parentId,
path: data[i].path,
name: data[i].name,
hidden: data[i].hidden,
component: () => import('../views' + data[i].component + '.vue'),
children: []
}
) //给子路由添加一条数据
router.addRoute(newT);
} else {
var Pid = newT.children.length - 1
let newR = router.options.routes[0].children[Pid];
newR.children.push(
{
id: data[i].id,
parentId: data[i].parentId,
path: data[i].path,
name: data[i].name,
hidden: data[i].hidden,
component: () => import('../views' + data[i].component + '.vue'),
}
) //给子路由添加一条数据
router.addRoute(newR);
}
}
next({
path: '/terminalList',
replace: true
});
} else {
next()
}
}
else {
next()
}
}
})
三、菜单栏展示,因为每个一级目录都有children。但首页菜单只有一个,没有下拉菜单
比如这样:
所以菜单展示的时候,判断下children的长度,没有值就只展示一个菜单