这是我参与「 第五届青训营 」伴学笔记创作活动的第 15 天
动态注册路由
一、全局注册路由的弊端
1、在类似于后台管理系统的项目中,会出现许多不同等级的角色,其中系统菜单的开放权限对每个角色来说是有差异的,比如管理员可以获取所有菜单权限,用户只能获取部分菜单权限
2、如果管理员先登录了,通过接口获取到了菜单,那么对应的路由也会被注册,此时如果再切换到用户的帐号,虽然菜单上不会出现管理员的菜单,但是因为管理员的菜单路由被全局注册了,所以当手动输入url的时候,是可以跳转到对应路由的,这就是路由全局注册的弊端
二、动态注册路由
1、为了解决以上的问题,可以通过动态路由来代替全局路由去配置路由
2、使用动态路由也有两种方式,第一种是基于角色的动态路由管理,这样根据不用的角色定义路由,也有一定的弊端,那就是每增加一个角色,都要重新发布一个新版本
const roles = {
"superadmin": [所有路由] => router.main.children,
"admin": [一部分路由] => router.main.children,
"service": [少部分路由] => router.main.children
}
3、第二种方法是基于菜单的动态路由管理,先获取userMenus动态展示菜单,再映射成路由对象,此时要求登录接口中请求三个内容:token、用户信息、菜单信息
4、具体的实现步骤:
-
根据菜单动态添加路由对象(将路由放在独立的文件中)
// router/main/... .ts export default { path: '/main/...', component: () => import('...') } -
动态获取所有路由对象(放在数组中)
function loadLocalRoutes() { const localRoutes: RouteRecordRaw[] = [] // 读取router/main中的所有ts文件 const files: Record<string, any> = import.meta.glob( '../../router/main/**/*.ts', { eager: true } ) for (const key in files) { const module = diles[key] localRoutes.push(module.default) } return localRoutes } -
根据菜单匹配正确路由
export function mapMenusToRoutes(userMenus: any[]) { // 1.加载本地路由 const localRoutes = loadLocalRoutes() // 2.根据菜单去匹配正确的路由 const routes: RouteRecordRaw[] = [] for (const menu of userMenus) { for (const submenu of menu.children) { const route = localRoutes.find((item) => item.path === submenu.url) if (route) routes.push(route) } } return routes }