答案是“先保底、再补权”:启动时仅注册/login、/404等静态公共路由;登录后异步获取菜单数据,转为RouteRecordRaw并用router.addRoute动态注入,存localStorage配合守卫实现刷新恢复与越权拦截。

核心思路是“先保底、再补权”:项目启动时只注册无需权限的静态路由(如登录页、404页),用户登录成功后,再异步获取菜单数据,转换为合法路由配置,动态注入,并配合全局守卫处理刷新恢复与越权拦截。
静态路由打底,确保未登录可访问
初始化 router 时,只硬编码基础路由,全部使用动态导入以支持懒加载:
-
/login:登录页,
hidden: true不出现在菜单中 - /404 或 /not-found:兜底页面
- / 重定向到 /dashboard,该 dashboard 组件也属于静态路由(用 layout 包裹)
登录后拉取并转换菜单数据
后端返回的菜单通常是扁平数组或树形结构,例如:
[{"path":"/user","name":"UserList","component":"user/List","meta":{"title":"用户列表"}}]前端需完成三件事才能生成合法的 RouteRecordRaw:
Element Plus Vue3 桌面组件库。在开发 Vue 3.x 页面时调用,使用 Element Plus 组件(如 el-button、el-input、el-form、el-table 等)。
立即学习“前端免费学习笔记(深入)”;
- 把
component: "user/List"转为异步组件:() => import('@/views/user/List.vue') - 确保
path是完整路径(避免嵌套时重复拼接),name全局唯一 - 补全
meta字段,如icon、hidden、roles,用于后续菜单渲染和守卫判断
注入路由 + 守卫兜底,防止白屏和越权
调用 router.addRoute(route)(Vue 3)注入后,新路由立即生效,但需注意几个关键点:
- 若用户刚跳转到
/user这类尚未注入的路径,需在守卫中手动next({ path: to.path })触发重匹配 - 全局前置守卫中判断:
!router.hasRoute(to.name) && 已登录→ 先拉菜单、注入路由、再放行 - 刷新页面会丢失动态路由,需将菜单存入
localStorage;守卫检测到有 token 但无对应路由时,优先读缓存并注入
登出时彻底清理,避免权限残留
用户退出必须清除所有动态路由痕迹:
- 遍历之前注入的路由
name,逐个调用router.removeRoute(name) - 清空
localStorage中缓存的菜单数据 - 重置 Pinia store 中的
menuList等侧边栏状态


















