当前位置: 首页 > Web前端 > vue.js

vuerouterv4.x路由动态加载的实现(完整代码)

时间:2023-03-31 22:22:06 vue.js

前言最近比较忙。整天呆在家里,总想写点什么。顺便说一句,我想加强代码水平。router4.0中添加路由的方法是从addRoutes()变成了addRoute(),和之前的实现有变化,但只是很小的变化。为什么不建议直接写入路由表?如果路由表固定在前端页面,用户可以访问所有页面,而后端需要一个和前端一样的路由表来配置权限,比较页面,根据返回相应的页面权限到不同的角色。如果修改了前端路由表,后端也需要同时修改,这样两端就需要同时维护。不仅麻烦,前端只能改源码,还可能因为忘记修改而导致bug。动态路由如果路由表是后台获取的,未经权限访问页面会返回404错误,只需要后台维护,权限控制更完善。本例具体实现不使用Vuex存储来自后端的路由列表数据。我认为没有必要。直接用sessionStorage存储就可以了,因为一旦刷新页面,Vuex中的数据就会消失,这时又得重新请求数据,会影响页面的加载速度。问题分析什么时候加载路由表?路由表加载后应该做什么?刷新如何重新加载?用户切换帐户时会发生什么?踩坑(回答上面的问题)异步加载router.beforeEach((to,from,next)=>{//注册动态路由registerRoutes().then(()=>{//跳转事件}).catch(()=>{//处理异常事件})});进行路由重定向,因为之前跳转的时候路由表中不存在该地址,如果直接next()是找不到页面的,所以需要重定向,这里需要做判断,否则会进入死循环。if(routeFlag){next();}else{//注册动态路由registerRoutes().then(()=>{routeFlag=true;next({...to,replace:true});}).catch(()=>{//处理异常事件})}首先判断用户token是否登录,如果登录,则获取sessionStorage中保存的路由表,进入beforeEach自动重新注册路由。sessionStorage中保存的路由表要去掉,否则切换账号后会获取到之前登录账号的路由表。完整代码Vue3+Router4+TypeScript//@/router/index.tsimport{createRouter,createWebHashHistory,RouteRecordRaw}from"vue-router";import{store}from"@/store";import{registerRoutes}from"@/router/dynamic";//基本页面constroutes:Array=[{path:"/login",name:"Login",component:()=>import("@/views/login.vue"),meta:{title:"Login",},},{path:"/register",name:"Register",component:()=>import("@/views/register.vue"),meta:{标题:"注册",},},{路径:"/",名称:"HomeIndex",组件:()=>import("@/views/index.vue"),meta:{title:"Home",},},];constrouter=createRouter({history:createWebHashHistory(),routes,});//防止无限路由循环letrouteFlag=false;router.beforeEach((to,from,next)=>{consttoken=store.state.user.token;如果(token){if(routeFlag){next();}else{//注册动态路由registerRoutes().then(()=>{routeFlag=true;next({...to,replace:true});}).catch(()=>{//处理异常事件})}}else{routeFlag=false;if(to.name==="登录"||to.name==="注册"){next();}else{next({name:"Login",query:{redirect:to.fullPath},});}}});导出默认路由器;类型定义我就不贴了,需要的话可以Write,不然typeof,sessionData封装方法就不贴了,也可以直接用localStorage.getItem()//@/router/dynamic.tsimportrouterfrom'@/router'import{sessionData}from"@/lib/storage";import{IAdminRoute}from"@/api/admin";import{ElLoading}from"element-plus";/***注册路由*用户切换账号时需要去掉sessionStorage中的routerMap数据*/exportconstregisterRoutes=():Promise=>{constrouterMap:IAdminRoute[]=sessionData.get("routerMap");returnnewPromise((resolve,reject)=>{//添加404页面router.addRoute({path:"/:catchAll(.*)",redirect:"/404",name:"NotFound",})if(routerMap.length){addRoutes(routerMap);resolve(true);}else{constloading=ElLoading.service();//模拟后端请求数据window.setTimeout(()=>{loading.close();constresult=[{path:"/product",name:"Product",组件:"layouts/page/index.vue",meta:{title:"ProductManagement",},children:[{path:"index",名称:“产品索引",component:"views/product/product-index.vue",meta:{title:"商品列表",auth:["delete"]},},{path:"detail",name:"ProductDetail",component:"views/product/product-detail.vue",meta:{title:"商品详情",auth:["upload"]},}],},{path:"/admin",name:"Admin",组件:"layouts/page/index.vue",meta:{title:"系统管理",},children:[{path:"index",name:"AdminIndex",component:"views/admin/admin-index.vue",meta:{title:"AdminList",auth:[“删除”,“审核”]},},{路径:“编辑”,名称:“AdminEdit”,组件:“views/admin/admin-edit.vue”,元:{隐藏:true,标题:“管理员编辑”,auth:[“添加”,“编辑”]},},{path:"role",name:"AdminRole",component:"views/admin/admin-role.vue",meta:{title:"AdminRole",},}],},];sessionData.set("routerMap",resultasnever);添加路由(结果);解决(真);},1000)}})}/***动态添加路由*/constaddRoutes=(routes:IAdminRoute[],parentName=""):void=>{routes.forEach((item)=>{if(item.path&&item.component){constcomponentString=item.component.replace(/^\/+/,""),//过滤字符串前面的所有'/'字符componentPath=componentString.replace(/\.\w+$/,"");//过滤掉后缀,以便为.vue添加import,否则会有警告...constroute={path:item.path,redirect:item.redirect,name:item.name,component:()=>import("@/"+componentPath+".vue"),meta:item.meta}parentName?路由器.addRoute(parentName,route):router.addRoute(route);如果(item.children&&item.children.length){addRoutes(item.children,item.name);}}})};/***生成管理菜单*/exportconstgetAuthMenu=()=>{//这里根据路由生成后台左侧菜单constrouterMap=sessionData.get("routerMap");}