Vue中用Pinia实现权限路由与菜单动态挂载的核心是登录后取权限数据→存入Pinia→解析并添加到router→渲染菜单;状态可追踪、可持久化、易测试,支持刷新续存、按钮级v-permission指令控制及全量路由过滤机制。

Vue 中用 Pinia 实现权限路由与菜单的动态挂载,核心是“登录后取权限数据 → 存入 Pinia → 解析并添加到 router → 渲染菜单”。整个过程不依赖全局变量,状态可追踪、可持久化、易测试。
权限数据存入 Pinia 状态仓库
新建一个 authStore,集中管理 token、用户角色、服务端返回的完整菜单/路由结构:
- 调用登录接口成功后,把后端返回的 nav 或 routes 数据(如树形菜单或扁平路由列表)存进 store 的 menuList 和 rawRoutes
- 建议配合
persist: true开启本地缓存,避免刷新后重复请求;若需敏感控制,改用 sessionStorage - 不要只存角色名(如 "admin"),而是存结构化数据——比如含
path、name、component、children、meta.title等字段的完整路由对象数组
动态解析并挂载路由到 Vue Router
在路由守卫 router.beforeEach 中判断是否已加载过动态路由,未加载则执行挂载逻辑:
递归分析 Vue 项目组件依赖,从入口文件生成组件层级图,支持 Vue 2/3,输出组件名、文件路径和属性。适用于分析组件结构、排查依赖或了解项目架构。
- 检查 Pinia 中
authStore.rawRoutes.length > 0且router.hasRoute('home')这类基础路由存在,再决定是否执行 addRoute - 遍历
rawRoutes,对每条路由调用router.addRoute();嵌套路由需先确保父级已存在(例如/dashboard要先加,子路由才能挂到它下面) - 组件路径使用动态导入:如
component: () => import(`@/views${item.component}.vue`),注意后端返回的 component 字段需约定好格式(如"sys/User"→ 对应src/views/sys/User.vue) - 挂载完成后,用
next({ ...to, replace: true })替换当前导航,避免重复触发守卫
菜单渲染与按钮级权限联动
菜单不是硬编码,而是基于 Pinia 中的 menuList 数据驱动生成:
立即学习“前端免费学习笔记(深入)”;
- 用
<el-menu>或自定义递归组件遍历authStore.menuList,只展示hidden !== true且有权限的项 - 每个菜单项的
index绑定为item.path,点击时router.push(item.path) - 按钮权限用自定义指令
v-permission="['sys:user:add']",指令内部读取 Pinia 中用户拥有的权限码列表(如从authStore.permissions获取),比对后控制显隐
处理页面刷新与路由丢失问题
刷新后路由消失?关键在于“首次进入时补全”:
- 在
main.ts或路由初始化后,检查authStore.token是否存在,存在就主动触发一次路由加载逻辑(而非只等守卫) - 避免在守卫中反复请求菜单接口,Pinia 持久化后,刷新直接读缓存数据即可解析挂载
- 若后端返回的是权限标识(如 ["user:list", "role:edit"])而非完整路由,则前端需维护一份全量路由表(
allRoutes),再按权限过滤出可用路由再 addRoute


















