在 Vue.js 中,动态路由是一种根据不同用户权限或其他因素动态改变路由列表的功能。这种机制允许开发者根据后端提供的权限数据动态渲染前端路由,实现多用户权限系统,不同用户展示不同的导航菜单。
动态路由的配置
动态路由的配置涉及到前端路由的动态加载和解析。通常,动态路由的数据存储在数据库中,前端通过接口获取当前用户对应的路由列表并进行渲染。以下是实现动态路由的基本步骤:
静态路由配置:首先,需要配置静态路由,如登录页、首页等。这些路由通常不会改变,可以直接写在路由配置文件中。
// 创建路由实例
const router = createRouter({
history: createWebHistory(import.meta.env.BASE_URL),
routes: allRoutes
})
// 所有路由定义(静态+动态)
const allRoutes = [
// 基础路由
{
path: '/',
name: 'login',
component: () => import("@/views/LoginView.vue")
},
{
path: '/404',
name: '404',
component: () => import('@/views/Error/404View.vue')
},
// 动态路由容器(登录后内容)
{
path: '/layout',
name: 'layout',
component: () => import('@/Layout/MainLayout.vue'),
children: [] // 初始为空,动态注入路由
},
]
动态路由获取:在用户登录后,前端调用后端接口获取用户对应的权限类型role。
// 需要权限控制的路由配置(扁平化结构更易管理)
const dynamicRouteConfigs = [
{
path: '/home', // 注意使用相对路径
name: 'home',
component: () => import('@/views/HomeView.vue'),
meta: {
title: '首页',
icon: 'House',
roles: ['*'] // *表示所有登录用户
}
},
{
path: 'user/list',
name: 'UserList',
component: () => import('@/views/user/ListView.vue'),
meta: {
title: '用户列表',
roles: ['1','2']
}
},
{
path: 'user/role',
name: 'UserRole',
component: () => import('@/views/user/RoleView.vue'),
meta: {
title: '角色管理',
roles: ['1']
}
}
]
路由过滤的函数
// 权限过滤方法修正
const filterRoutes = (routes, roles) => {
// 递归处理每个路由节点
return routes.filter(route => {
// 获取当前路由需要的权限角色
const requiredRoles = route.meta?.roles || []
// 检查当前路由是否满足权限要求
const hasPermission = requiredRoles.includes('*') || requiredRoles.includes(roles + '')
// 递归处理子路由(关键修改点)
if (route.children) {
const filteredChildren = filterRoutes(route.children, roles)
// 保留有效子路由:只有当子路由存在时才保留children
route.children = filteredChildren.length ? filteredChildren : undefined
}
/*
路由保留条件(核心逻辑):
1. 当前路由自身有权限 或
2. 存在有效的子路由(即使当前路由没有权限,但子路由有权限时保留父级容器)
*/
return hasPermission || (route.children && route.children.length > 0)
})
}
动态添加路由,先清空已有的动态路由,然后再调用添加路由的函数进行添加,
// 动态添加路由到layout
const addDynamicRoutes = (roles) => {
// 清空已有动态路由
const layout = router.getRoutes().find(r => r.name === 'layout')
layout.children.forEach(child => {
router.removeRoute(child.name)
})
// 过滤并添加新路由
const allowedRoutes = filterRoutes(dynamicRouteConfigs, loginStore().roles);
allowedRoutes.forEach(route => { router.addRoute('layout', route); });
console.log(allowedRoutes);
sessionStorage.setItem('menuPath',JSON.stringify(allowedRoutes));//存储的筛选过的动态路由
sessionStorage.setItem('menuName',JSON.stringify(router.getRoutes()));//存储的所有动态路由
console.log(router.getRoutes());
// 确保404最后处理
router.addRoute({
path: '/:pathMatch(.*)*',
redirect: '/404'
})
}
导航守卫部分,路由跳转前的操作。
获取用户状态存储实例,检测登录状态;判断用户未登录时直接跳转到登录页进行登录;已登录访问登录页处理,防止已登录用户重复访问登录页;动态路由注入。
使用router.addRoute()注入路由;路由跳转处理,清除旧路由(避免重复);
// 路由守卫修改部分(router/index.ts)
router.beforeEach(async (to, from, next) => {
const store = loginStore()
const isLogin = !!store.id
// 未登录状态处理
if (!isLogin) {
return to.path === '/' ? next() : next('/')
}
// 已登录但访问登录页时重定向
if (to.path === '/') {
return next('/home')
}
// 动态路由加载逻辑
if (!store.routesLoaded) {
try {
// 直接从store获取已保存的角色信息
const userRoles = store.roles
console.log(userRoles);
// 如果角色信息不存在则抛出错误
if (!userRoles || userRoles.length === 0) {
throw new Error('用户角色信息未获取')
}
// 添加动态路由
addDynamicRoutes(userRoles)
// 在添加路由后打印
console.log('当前所有路由:', router.getRoutes().map(r => r.path))
// 更新加载状态
store.setRoutesLoaded(true)
// 使用replace方式跳转避免重复记录历史
return next({ ...to, replace: true })
} catch (error) {
console.error('路由加载失败:', error)
// 清除用户状态并跳转登录页
store.$reset()
return next('/')
}
}
next()
})
最后,总结整个流程,强调关键点,帮助用户全面理解路由守卫的工作机制和实现动态路由加载的正确方法。
本文详细介绍了在Vue.js中实现动态路由和权限控制的步骤,包括路由配置、动态路由获取、路由过滤、动态添加路由以及导航守卫的使用。通过这些步骤,可以有效地根据用户权限动态渲染前端路由,实现多用户权限系统。