Vue动态路由,结合后端接口实现
话不多说,直接上干货。
首先声明我们的固定路由,后面系统需要用到的路由则可以在此基础上进行动态添加。
1 //固定的路由 2 const routes = [{ 3 path: '/', 4 component: login, 5 meta: { 6 title: '登录', 7 Breadcrumb: false 8 }, 9 isHidden: true, //是否隐藏 10 children: [] 11 }, 12 { 13 path: '/login', 14 component: login, 15 meta: { 16 title: '登录', 17 Breadcrumb: false 18 }, 19 isHidden: true, //是否隐藏 20 children: [] 21 }, 22 ]
此处用到自定义字典结构dictionary.js;
//dictionary.js;
1 var list = []; 2 class dictionary { 3 set(key, value) { 4 list.push({ 5 key: key, 6 value: value, 7 }) 8 } 9 get(key) { 10 var component=null; 11 list.forEach(item => { 12 if (item.key == key) 13 component=item.value; 14 }) 15 16 return component; 17 } 18 } 19 20 export default dictionary
系统登录时调用方法同步获取当前的拥有权限的菜单
1 //获取动态路由方法 2 async function getRouterList(that,postFun,successCallback) { 3 routerPath = ''; 4 //登录之后获取动态路由 5 let userRouter = []; 6 let userMenu = []; 7 var data = await getData(); 8 userRouter = data; //获取路由 9 userRouter = sort(userRouter); 10 //从接口获取菜单路由 11 function getData() { 12 return new Promise(resolve => { 13 let para = { 14 urls: '后端获取权限列表的接口地址', 15 isShowLoading: false,//是否显示加载状态 16 }; 17 postFun(para).then(res => { 18 if (res.code == 200) { 19 data = res.value; 20 if (!data) { 21 that.$message.error('你没有任何权限请联系管理员分配权限'); 22 that.$router.push('/login'); 23 } else { 24 resolve(data); 25 } 26 } else { 27 that.$message.error('获取权限失败,请稍后重试'); 28 that.$router.push('/login'); 29 } 30 }).catch(err => { 31 32 }); 33 }); 34 }
获取到权限结构后组装成路由格式并调用路由拼接将系统路由组织完整
routes.concat(userRouter)
此时如果用户强制刷新浏览器,将再次获取当前的路由以确定权限是否有变化保证当前用户的权限始终保持与后台配置一致。
具体做法在main.js中添加逻辑判断代码如下:
1 if (sessionStorage.getItem('token')) { 2 //这里是调用router.js里的方法拿到动态路由 3 Vue.prototype._router.getRouterList(Vue,Vue.prototype.postFun, function(routerData, userMenu) { 4 //动态添加路由 5 router.addRoutes(routerData) 6 router.options.routes = [...userMenu]; 7 }) 8 } else { 9 router.push('/login'); 10 } 11 //路由守卫 12 router.beforeEach((to, from, next) => { 13 //NProgress.start(); 14 if (to.path == '/login') { 15 sessionStorage.removeItem('token'); 16 } 17 let user = sessionStorage.getItem('token'); 18 if (!user && to.path != '/login') { 19 next({ 20 path: '/login' 21 }) 22 } 23 next(); 24 })
这样就完成了我们vue的动态路由和使用。完整的动态路由router.js代码如下:

1 import dictionary from './dictionary' 2 const login = () => import('@/views/login/login') 3 const home = () => import('@/views/master/Home') 4 var routerPath = ''; 5 6 var map = new dictionary(); 7 /*------------------------------------------主页-------------------------------------------------------------------------*/ 8 map.set("home",resolve => require(['@/views/home/home'], resolve)); 9 /*-------------------------------------------系统-------------------------------------------------------------------------*/ 10 map.set("roleManagement",resolve => require(['@/views/systemManagement/roleManagement/roleList'], resolve)) //系统角色管理 11 map.set("systemUserManagement",resolve => require(['@/views/systemManagement/systemUserManagement/systemUserList'], resolve)); //系统用户管理 12 map.set("menuManagement",resolve => require(['@/views/systemManagement/menuManagement/menuList'], resolve)); //菜单管理 13 map.set("fileManagement",resolve => require(['@/views/systemManagement/fileManagement/fileList'], resolve)); //文件管理 14 map.set("contentManagement",resolve => require(['@/views/systemManagement/contentManagement/contentList'], resolve)); //内容管理 15 map.set("smsSendRecord",resolve => require(['@/views/systemManagement/smsSendRecord/smsSendRecordList'], resolve)); //短信 16 /*-----------------------------------------------赛事管理-------------------------------------------------------------------------*/ 17 map.set("scorerLoginPage",resolve => require(['@/views/matchManagement/scorerLoginPage/scorerLoginPageList'], resolve)); //记分长登录页管理 18 map.set("match",resolve => require(['@/views/matchManagement/match/matchList'], resolve)); //比赛管理 19 map.set("accountAuthorization",resolve => require(['@/views/matchManagement/accountAuthorization/accountAuthorList'], resolve)); //账号授权管理 20 /*-----------------------------------------------用户管理-------------------------------------------------------------------------*/ 21 map.set("user",resolve => require(['@/views/userManagement/users/userList'], resolve)); //用户列表 22 map.set("orderMatch",resolve => require(['@/views/userManagement/orderMatch/orderList'], resolve)); //赛事订单管理 23 map.set("orderReal",resolve => require(['@/views/userManagement/orderReal/orderList'], resolve)); //实名订单管理 24 map.set("player",resolve => require(['@/views/userManagement/player/playerList'], resolve)); //选手列表 25 map.set("qrCode",resolve => require(['@/views/userManagement/qrCode/qrCodeList'], resolve)); //二维码数据 26 27 28 //获取动态路由方法 29 async function getRouterList(that,postFun,successCallback) { 30 routerPath = ''; 31 //登录之后获取动态路由 32 let userRouter = []; 33 let userMenu = []; 34 var data = await getData(); 35 userRouter = data; //获取路由 36 userRouter = sort(userRouter); 37 //从接口获取菜单路由 38 function getData() { 39 return new Promise(resolve => { 40 let para = { 41 urls: '/sys/account/permissions', 42 isShowLoading: false, 43 }; 44 postFun(para).then(res => { 45 if (res.code == 200) { 46 data = res.value; 47 if (!data) { 48 that.$message.error('你没有任何权限请联系管理员分配权限'); 49 that.$router.push('/login'); 50 } else { 51 resolve(data); 52 } 53 } else { 54 that.$message.error('获取权限失败,请稍后重试'); 55 that.$router.push('/login'); 56 } 57 }).catch(err => { 58 59 }); 60 }); 61 } 62 //路由菜单排序 63 function sort(userRouter) { 64 var router = []; 65 var routerTo = []; 66 userRouter.forEach(item => { 67 if (item.parentId ==-1) { 68 var children = []; 69 var menuChildren = []; 70 router.push({ 71 sort: item.sort, 72 path: '/', 73 component: home, 74 icon: item.icon, 75 key: item.id, 76 meta: { 77 title: item.name, 78 Breadcrumb: isHaveSubMenus(userRouter, item.id), 79 }, 80 isHidden: false, //是否隐藏 81 children: children, 82 }); 83 //菜单 84 userMenu.push({ 85 sort: item.sort, 86 path: item.path, 87 icon: item.icon, 88 key: item.id, 89 meta: { 90 title: item.name, 91 Breadcrumb: true 92 }, 93 isHidden: false, //是否隐藏 94 children: menuChildren, 95 }); 96 97 if (!isHaveSubMenus(userRouter, item.id)) { 98 children.push({ 99 sort: item.sort, 100 path: item.path, 101 icon: item.icon, 102 key: item.id, 103 meta: { 104 title: item.name, 105 Breadcrumb: true 106 }, 107 isHidden: false, 108 component: map.get(item.path.split('/')[1]), 109 }); 110 } 111 getSubMenus(item, userRouter, children, menuChildren); 112 } 113 }); 114 router.sort(sortASC); 115 userMenu.sort(sortASC); 116 //获取第一个菜单路由 117 userMenu.forEach(item1 => { 118 if (routerPath == '' && item1.path != '/') { 119 routerPath = item1.path; 120 } 121 }); 122 if (routerPath == '') { 123 userMenu.forEach(item => { 124 if (item.children && item.children.length > 0) { 125 item.children.forEach(itemSub => { 126 if (routerPath == '') { 127 routerPath = itemSub.path; 128 } 129 }) 130 } 131 }) 132 } 133 return router; 134 } 135 136 function isHaveSubMenus(menus, parentId) { 137 var list = []; 138 menus.forEach(item => { 139 if (item.parentId == parentId) 140 list.push(item.id); 141 }); 142 143 return list.length > 0; 144 } 145 //获取子菜单路由 146 function getSubMenus(parent, data, children, menuChildren) { 147 data.forEach(item => { 148 if (item.parentId == parent.id) { 149 //路由 150 children.push({ 151 sort: item.sort, 152 path: item.path, 153 icon: item.icon, 154 key: item.id, 155 meta: { 156 title: item.name, 157 Breadcrumb: true 158 }, 159 isHidden: false, 160 component: map.get(item.path.split('/')[1]), 161 }); 162 //菜单 163 menuChildren.push({ 164 sort: item.sort, 165 path: item.path, 166 icon: item.icon, 167 key: item.id, 168 meta: { 169 title: item.name, 170 Breadcrumb: true 171 }, 172 isHidden: false, //是否隐藏 173 }); 174 } 175 }); 176 if (children.length > 0) 177 children.sort(sortASC); 178 if (menuChildren.length > 0) 179 menuChildren.sort(sortASC); 180 } 181 182 function sleep(time) { 183 return new Promise((resolve) => setTimeout(resolve, time)); 184 } 185 186 //固定的路由 187 const routes = [{ 188 path: '/', 189 component: login, 190 meta: { 191 title: '登录', 192 Breadcrumb: false 193 }, 194 isHidden: true, //是否隐藏 195 children: [] 196 }, 197 { 198 path: '/login', 199 component: login, 200 meta: { 201 title: '登录', 202 Breadcrumb: false 203 }, 204 isHidden: true, //是否隐藏 205 children: [] 206 }, 207 ] 208 successCallback(routes.concat(userRouter), userMenu, routerPath) 209 } 210 export default { 211 getRouterList, 212 }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!