路由
打开 main.ts
文件看,和路由相关的注册事件有两个
setupRouter(app);
setupRouterGuard(router);
路由列表是一个函数,第二个函数执行的是一些路由守卫的逻辑
基础路由
在 setupRouter
中,通过下面的代码可以知道核心的路由信息在 basicRoutes
export const router = createRouter({
// 创建一个 hash 历史记录。
history: createWebHashHistory(import.meta.env.VITE_PUBLIC_PATH),
// 应该添加到路由的初始路由列表。
routes: basicRoutes as unknown as RouteRecordRaw[],
// 是否应该禁止尾部斜杠。默认为假
strict: true,
scrollBehavior: () => ({ left: 0, top: 0 }),
});
basicRoutes
主要记录了一些静态的页面路由,比如登录、登录页面、结果页面等。这些页面不涉及权限,将其设置为基础的路由页面。
// src\router\routes\index.ts
export const basicRoutes = [
LoginRoute,
RootRoute,
...mainOutRoutes,
REDIRECT_ROUTE,
PAGE_NOT_FOUND_ROUTE,
];
这些页面没有权限逻辑,单纯是为了某些特殊情况下用来展示的页面,功能页面如登录,状态展示页面如 404,403 等页面
权限路由
上面路由是所有人都可以看到的,也是在初始化页面时候默认会显示的一些路由。 但是我们还需要一部分的路由和角色用户绑定,比如说管理员可以做看到一些管理页面,但是普通员工却看不到。
对于这类页面的权限绑定,我们会通过当前登录的用户信息,判断它下面有哪些权限路由,有的话添加到 routes
数组中,没有的话就过滤除去。
vue-vben-admin
的路由存放在 src/router/routes 下面。 src/router/routes/modules用于存放路由模块,在该目录下的文件会自动注册。
const modules = import.meta.glob("./modules/**/*.ts", { eager: true });
通过上面的代码,将 modules 下面所有以 ts 结尾的文件,都会收集到 modules 变量中。
import.meta.glob
可以将文件系统导入生成如下的数据
const modules = {
"./dir/foo.js": () => import("./dir/foo.js"),
"./dir/bar.js": () => import("./dir/bar.js"),
};
在进入到具体的 modules
文件夹下的内容来看,我们以 src\router\routes\modules\about.ts
为例
const about: AppRouteModule = {
path: "/about",
name: "About",
component: LAYOUT,
redirect: "/about/index",
meta: {
hideChildrenInMenu: true,
icon: "simple-icons:about-dot-me",
title: t("routes.dashboard.about"),
orderNo: 100000,
},
children: [
{
path: "index",
name: "AboutPage",
component: () => import("/@/views/sys/about/index.vue"),
meta: {
title: t("routes.dashboard.about"),
icon: "simple-icons:about-dot-me",
hideMenu: true,
},
},
],
};
export default about;
可以发现我们的每个 modules
下面的 ts 文件配置了我们路由的信息。
拿到 modules
后,再通过 Object.keys
进行循环处理,解析出我们的路由routeModuleList
Object.keys(modules).forEach((key) => {
const mod = (modules as Recordable)[key].default || {};
const modList = Array.isArray(mod) ? [...mod] : [mod];
routeModuleList.push(...modList);
});
通过上面的转换,最终我们可以获得如下的数据
[
{
"path": "/about",
"name": "About",
"redirect": "/about/index",
"meta": {
"hideChildrenInMenu": true,
"icon": "simple-icons:about-dot-me",
"title": "routes.dashboard.about",
"orderNo": 100000
},
"children": [
{
"path": "index",
"name": "AboutPage",
"meta": {
"title": "routes.dashboard.about",
"icon": "simple-icons:about-dot-me",
"hideMenu": true
}
}
]
},
...
]
将其赋值给我们的路由变量 asyncRoutes
还记得我们最开始执行的一个 setupRouterGuard(router);
函数么
在这个函数里面会执行 permissionStore.buildRoutesAction()
函数
它会通过各种权限模式,将我们的 asyncRoutes
做过滤
switch (permissionMode) {
// 角色权限
case PermissionModeEnum.ROLE:
// 对非一级路由进行过滤
routes = filter(asyncRoutes, routeFilter);
// 对一级路由根据角色权限过滤
routes = routes.filter(routeFilter);
// Convert multi-level routing to level 2 routing
// 将多级路由转换为 2 级路由
routes = flatMultiLevelRoutes(routes);
break;
...
}
至此,最后 routes
剩下来的内容,就是我们当前用户可以看到的路由,也就是左侧菜单可以查看的