权限路由动态注册使用说明和完整示例
一、 核心原理与使用说明路由分层将路由分为constantRoutes无需权限的静态路由如登录、404和asyncRoutes需要权限的动态路由。组件懒加载Vite 不支持require.context必须使用import.meta.glob批量导入views下的组件。动态挂载使用 Vue Router 4 提供的router.addRoute()将过滤后的路由添加到指定的父级布局Layout下。刷新防丢失页面刷新会导致内存中的动态路由丢失。必须在router.beforeEach中判断如果已登录但路由未生成则重新拉取权限并生成路由最后使用next({ ...to, replace: true })重新触发导航。菜单联动侧边栏菜单应直接读取生成后的路由表结合meta字段保证路由与菜单的绝对一致。二、 完整实战示例1. 定义路由表 (src/router/routes.ts)importtype{RouteRecordRaw}fromvue-router// 1. 静态路由无需权限exportconstconstantRoutes:RouteRecordRaw[][{path:/login,name:Login,component:()import(/views/login/index.vue),meta:{hidden:true}},{path:/404,name:NotFound,component:()import(/views/error/404.vue),meta:{hidden:true}}]// 2. 动态路由需要权限// 注意必须配置 name否则重置路由时可能会出问题exportconstasyncRoutes:RouteRecordRaw[][{path:/system,name:System,component:()import(/layouts/DefaultLayout.vue),redirect:/system/user,meta:{title:系统管理,icon:setting,roles:[admin]},children:[{path:user,name:SystemUser,component:()import(/views/system/user/index.vue),meta:{title:用户管理,roles:[admin]}},{path:role,name:SystemRole,component:()import(/views/system/role/index.vue),meta:{title:角色管理,roles:[admin]}}]},// ️ 404 兜底路由必须放在最后动态添加{path:/:pathMatch(.*)*,redirect:/404,meta:{hidden:true}}]2. 封装权限 Store (src/stores/modules/permission.ts)import{ref}fromvueimport{defineStore}frompiniaimporttype{RouteRecordRaw}fromvue-routerimport{asyncRoutes,constantRoutes}from/router/routes// 使用 Vite 的 import.meta.glob 预加载所有视图组件constmodulesimport.meta.glob(/views/**/*.vue)exportconstusePermissionStoredefineStore(permission,(){constroutesrefRouteRecordRaw[]([])constisRoutesGeneratedref(false)// 核心根据角色过滤路由functionfilterAsyncRoutes(routeList:RouteRecordRaw[],roles:string[]):RouteRecordRaw[]{constres:RouteRecordRaw[][]routeList.forEach(route{consttmp{...route}if(hasPermission(tmp,roles)){if(tmp.children){tmp.childrenfilterAsyncRoutes(tmp.children,roles)}// 将字符串组件路径转换为真实的懒加载组件if(typeoftmp.componentstring){tmp.componentmodules[/src/views/${tmp.component}.vue]}res.push(tmp)}})returnres}functionhasPermission(route:RouteRecordRaw,roles:string[]):boolean{if(route.meta?.roles){returnroles.some(role(route.meta!.rolesasstring[]).includes(role))}returntrue}// 生成动态路由并缓存functiongenerateRoutes(roles:string[]):RouteRecordRaw[]{letaccessedRoutes:RouteRecordRaw[]if(roles.includes(admin)){accessedRoutesasyncRoutes||[]}else{accessedRoutesfilterAsyncRoutes(asyncRoutes,roles)}routes.valueconstantRoutes.concat(accessedRoutes)isRoutesGenerated.valuetruereturnaccessedRoutes}// 退出登录时重置functionresetRoutes(){routes.value[]isRoutesGenerated.valuefalse}return{routes,isRoutesGenerated,generateRoutes,resetRoutes}})3. 配置路由守卫 (src/router/index.ts)import{createRouter,createWebHistory}fromvue-routerimport{constantRoutes}from./routesimport{useUserStore}from/stores/modules/userimport{usePermissionStore}from/stores/modules/permissionconstroutercreateRouter({history:createWebHistory(import.meta.env.BASE_URL),routes:constantRoutes,scrollBehavior:()({top:0})})constwhiteList[/login]router.beforeEach(async(to,from,next){constuserStoreuseUserStore()constpermissionStoreusePermissionStore()if(userStore.token){if(to.path/login){next({path:/})}else{// 核心逻辑已登录但尚未生成动态路由if(!permissionStore.isRoutesGenerated){try{// 1. 获取用户信息包含角色/权限awaituserStore.fetchUserInfo()// 2. 生成可访问的路由表constaccessRoutespermissionStore.generateRoutes(userStore.roles)// 3. 动态挂载到路由实例accessRoutes.forEach(route{router.addRoute(route)})// 4. ️ 必须重新导航否则新添加的路由不会立即生效next({...to,replace:true})}catch(error){// 获取用户信息失败如 Token 过期重置状态并跳转登录awaituserStore.logout()next(/login?redirect${to.path})}}else{next()}}}else{// 未登录if(whiteList.indexOf(to.path)!-1){next()}else{next(/login?redirect${to.path})}}})exportdefaultrouter三、 进阶后端返回路由表模式如果后端直接返回路由 JSON 结构如component: system/user/index只需修改generateRoutes中的组件解析逻辑// 后端返回的数据结构示例// { path: /system, component: DEFAULT_LAYOUT, children: [{ path: user, component: system/user/index }] }functionmapBackendRoutes(serverRoutes:any[]):RouteRecordRaw[]{returnserverRoutes.map(item{constroute:any{...item}// 处理布局组件if(item.componentDEFAULT_LAYOUT){route.component()import(/layouts/DefaultLayout.vue)}elseif(item.component){// 动态匹配 views 下的组件constcomponentPath/src/views/${item.component}.vueroute.componentmodules[componentPath]}// 递归处理子路由if(item.children){route.childrenmapBackendRoutes(item.children)}returnroute})}四、 避坑指南刷新白屏/404确保在beforeEach中调用了next({ ...to, replace: true })因为addRoute不会触发当前页面的重新渲染。404 路由位置/:pathMatch(.*)*必须在动态路由全部添加完毕后才生效。如果一开始就写在静态路由里会导致动态路由还没加载就被 404 拦截。Vite 路径匹配import.meta.glob返回的 key 是绝对路径如/src/views/user/index.vue拼接时注意不要漏掉/src/前缀。路由 Name 唯一性动态路由的name必须全局唯一否则addRoute会覆盖同名路由导致页面错乱。

相关新闻

前列腺癌一线升级阿帕他胺Apalutamide提前阻断远处转移【海得康】

前列腺癌一线升级阿帕他胺Apalutamide提前阻断远处转移【海得康】

前列腺癌的疾病进展是一个连续的过程,从局部高危转移风险阶段,到非转移去势抵抗阶段,最终会进展为广泛转移的终末期,传统单纯雄激素剥夺治疗作为一线方案,无法完全阻断雄激素受体通路的后续激活,近60%的高危…

2026/7/22 14:22:22阅读更多 →
070、TensorFlow Lite Micro的Deployment项目:部署到生产环境

070、TensorFlow Lite Micro的Deployment项目:部署到生产环境

070 TensorFlow Lite Micro的Deployment项目:部署到生产环境 昨晚凌晨两点,我在产线上盯着那块STM32U5开发板,串口输出突然卡死在“AllocateTensor failed”上。旁边测试工程师递来一杯冷掉的咖啡,说“这板子上午还跑得好好的”。我盯着调试器里那个0xDEADBEEF的地址,突然…

2026/7/22 14:20:22阅读更多 →
泉州不住家阿姨哪家实力强

泉州不住家阿姨哪家实力强

在泉州生活节奏越来越快的今天,不少家庭开始考虑请一位不住家阿姨,既能分担家务、照顾老人孩子,又不必占用家中多余房间。但面对市场上良莠不齐的家政公司,很多人都会问:泉州不住家阿姨到底哪家更靠谱? 今天…

2026/7/22 14:20:22阅读更多 →
SATA控制器寄存器配置实战:从PLL锁定到信号完整性优化

SATA控制器寄存器配置实战:从PLL锁定到信号完整性优化

1. 项目概述与核心价值 在嵌入式系统,尤其是涉及高速串行通信的SoC(片上系统)设计中,硬件工程师和驱动开发者经常会遇到一个既关键又令人头疼的环节:寄存器配置。你手头可能有一份几百甚至上千页的芯片手册&#xff0c…

2026/7/22 15:20:39阅读更多 →
医疗问答大模型的越狱:让模型开具违规处方的诱导路径

医疗问答大模型的越狱:让模型开具违规处方的诱导路径

医疗问答大模型的越狱:让模型开具违规处方的诱导路径 一、当模型开始开处方:医疗问答的合规悬崖 医疗问答大模型上线后,最常见的滥用方向"让它开药"。处方权在现实里受严格管制,但在对话窗口里,模型只要被…

2026/7/22 15:20:39阅读更多 →
事务与锁的进阶实战:读懂死锁日志之外的锁等待链

事务与锁的进阶实战:读懂死锁日志之外的锁等待链

大家好,我是小耶,写功课只是为了我踩过的坑,你们别再踩了!前几周我们讲了死锁排查——怎么读SHOW ENGINE INNODB STATUS、怎么从日志里找到两个冲突的事务。但死锁只是锁问题的“冰山一角”。死锁会直接报错,你一眼就能…

2026/7/22 15:20:39阅读更多 →
等保合规威胁建模:把监管要求翻译成架构层面的控制点

等保合规威胁建模:把监管要求翻译成架构层面的控制点

等保合规威胁建模:把监管要求翻译成架构层面的控制点 一、条款很抽象,架构很具体:等保落地的断层 等保(网络安全等级保护)的条款,写的是"应采取""应实现""应审计"这样的原则…

2026/7/22 15:20:39阅读更多 →
Canvas粒子系统实现情绪化动画:从烟花易冷看代码艺术创作

Canvas粒子系统实现情绪化动画:从烟花易冷看代码艺术创作

那天晚上,我正为一个项目渲染一段粒子特效,屏幕上的光点明明灭灭,忽然就想起了很多年前用代码模拟烟花的日子。那些简单的二维动画,没有复杂的三维模型和物理引擎,却总能精准地触动人心。于是,我关掉了庞大…

2026/7/22 15:20:39阅读更多 →
Unity异步编程实战:深入理解async与await的应用技巧

Unity异步编程实战:深入理解async与await的应用技巧

1. 项目概述:为什么Unity开发者必须掌握异步编程? 如果你在Unity里写过需要加载资源、等待网络请求或者执行耗时计算的代码,大概率遇到过游戏卡顿、界面冻结的尴尬情况。传统的协程(Coroutine)虽然能解决一部分问题&am…

2026/7/22 15:18:39阅读更多 →
Go语言静态资源打包方案对比与实践指南

Go语言静态资源打包方案对比与实践指南

1. 项目背景与核心需求在Go语言开发中,我们经常需要处理静态资源文件的打包问题。无论是Web应用的模板文件、前端资源,还是配置文件、证书等,都需要随程序一起分发。传统做法是将这些文件与编译后的二进制文件放在同一目录下,但这…

2026/7/22 0:53:59阅读更多 →
Go语言实现高性能LDAP认证服务的架构与实践

Go语言实现高性能LDAP认证服务的架构与实践

1. 项目背景与核心价值LDAP(轻量级目录访问协议)作为企业级身份认证的黄金标准,已经服务了超过80%的财富500强公司。我在金融科技领域实施统一认证体系时,发现传统Java方案存在启动慢、内存占用高等痛点。而Go语言凭借其协程并发模…

2026/7/22 0:53:59阅读更多 →
【AI面试官实战指南】:用ChatGPT模拟10类高频技术岗面试,3天提升应答精准度92%

【AI面试官实战指南】:用ChatGPT模拟10类高频技术岗面试,3天提升应答精准度92%

更多请点击: https://intelliparadigm.com 第一章:AI面试官实战指南的核心价值与适用场景 AI面试官并非替代人类HR的“黑箱工具”,而是以可解释、可审计、可迭代的方式,赋能招聘全链路的关键基础设施。其核心价值在于将主观经验沉…

2026/7/22 0:53:59阅读更多 →
中小企业小程序开发公司怎么选:预算、上手和售后避坑指南

中小企业小程序开发公司怎么选:预算、上手和售后避坑指南

中小企业做小程序,最常见的矛盾是预算有限,但又不希望功能太单薄;没有技术团队,但又希望后续能自己运营;想快速上线,又担心隐性收费和售后失联。选型时如果只看“低价套餐”或“案例数量”,很容…

2026/7/22 0:01:17阅读更多 →
GEO优化如何沉淀长期内容资产?广拓时代谈AI搜索时代的内容ROI

GEO优化如何沉淀长期内容资产?广拓时代谈AI搜索时代的内容ROI

企业做营销,最怕钱花完了,资产没有留下。 效果广告能带来一段时间的曝光,但预算停止后,流量往往也随之停止。短视频内容可能在几天内冲高,也可能很快沉下去。AI搜索时代,企业需要重新思考一个问题&#xff…

2026/7/22 0:01:17阅读更多 →
Agent 终态判定:何时该停止思考、给出最终回复

Agent 终态判定:何时该停止思考、给出最终回复

Agent 终态判定:何时该停止思考、给出最终回复 一、你的 Agent 在"再想想"的循环里绕了 12 轮,用户已经关窗口了 Agent 与人最大的区别是:人知道什么时候该停下来给答案,Agent 会一直"想"下去。你给 Agent 接…

2026/7/22 0:01:17阅读更多 →
YOLOv8推理性能优化:从1.2FPS到35FPS的全链路加速实践

YOLOv8推理性能优化:从1.2FPS到35FPS的全链路加速实践

如果你在部署 YOLOv8 时,发现推理速度只有可怜的 1-2 FPS,而别人的演示视频却能跑到 30 FPS 以上,那么问题很可能不在模型本身,而在于你的整个处理链路。很多开发者拿到一个训练好的 YOLOv8 模型后,会直接使用官方示例…

2026/7/21 22:53:50阅读更多 →
Coze与Dify对比指南:低代码AI应用开发从入门到实战

Coze与Dify对比指南:低代码AI应用开发从入门到实战

1. 从零到一:为什么你需要了解 Coze 和 Dify?如果你对 AI 应用开发感兴趣,但一看到“大模型”、“智能体”、“工作流”这些词就头疼,觉得门槛太高,那这篇文章就是为你准备的。很多开发者,包括我自己&#…

2026/7/21 18:53:30阅读更多 →
AI生图工具怎么选?2026年6月版实测对比

AI生图工具怎么选?2026年6月版实测对比

做自媒体的朋友应该都有体会:配图一直是个让人头疼的问题。2026年,AI生图工具已经非常成熟了,但工具太多反而不知道怎么选。以下是截至2026年6月我对主流AI生图工具的实测对比。Midjourney V8.1:速度之王2026年6月11日&#xff0c…

2026/7/21 18:53:30阅读更多 →