首页IT科技vue admin template动态路由(vue2后台管理项目动态加载路由)

vue admin template动态路由(vue2后台管理项目动态加载路由)

时间2025-07-04 16:51:47分类IT科技浏览4751
导读:项目思路描述 1.后台返回一个json格式的路由表,我这里直接写死了数据,使用Promise返回,大家可参考,也可以自己造;...

项目思路描述

1.后台返回一个json格式的路由表            ,我这里直接写死了数据                   ,使用Promise返回       ,大家可参考      ,也可以自己造;

2.因为后端传回来的都是字符串格式的                   ,但是前端这里需要的是一个组件对象             ,所以要写个方法遍历一下      ,将字符串转换为组件对象;

3.利用vue-router的beforeEach             、addRoutes                   、localStorage来配合上边两步实现效果;

4.左侧菜单栏根据拿到转换好的路由列表进行展示;

在拦截路由之前                   ,我们还得先定义好静态路由             ,然后从后端取到动态路由之后,进行合并            。 修改 router/index.js 静态路由主要是登录页面和重定向页面等                    , 生成全局路由变量

import Layout from @/components/layout const constantRoutes = [ { path: /, redirect: /home }, { path: /login, component: () => import(@/views/login.vue), meta: { title: 登录 }, name: Login }, // 后台返回动态路由 // { // path: /home, // component: Layout, // hidden: true, // redirect: /list, // children: [ // { // path: /list, // name: List, // component: () => import(@/views/index.vue), // meta: { // index: 1                    , // meta: { title: xxxxx, }, // } // }, // { // path: /shipInfo, // component: () => import(@/views/xxxx.vue), // meta: { title: xxxx}, // name: ShipInfo // }, // { // path: /quality, // component: () => import(@/views/xxxx.vue), // meta: { title: xxxxx }, // name: Quality // }, // ] // }, ]; const router =createRouter({ history:createWebHistory(), routes:constantRoutes , //使用浏览器的回退或者前进时,重新返回时保留页面滚动位置            ,跳转页面的话                    ,不触发                   。 scrollBehavior(to,from,savePosition){ if(savePosition){ return savePosition; }else{ return {top:0}; } } }); export default router;

后端动态路由

路由在实际项目中是通过后端接口返回       ,在日常的开发中可以根据后端格式写手动写死            ,前后端联调的时候换成接口就行了       。(api下新建menujs)

其实就是一个路由配置项                   ,里面的path       ,name      ,component                   ,children             ,meta都是关键字不能改      ,格式一定要完全一样                   ,其中meta里可以带上我们需要的信息             ,比如面包屑,菜单渲染的名字                   ,图标                    ,是否需要缓存,角色限制等            ,项目中需要用到的都可以存在meta中      。 //模拟获取后台路由(动态路由) export function getRouters() { return new Promise((resolve, reject) => { // menuList 里面得参数自己定义(可以跟后端商量返回自己需要的格式) // 这点一定要和后端商量好                    ,这个路由表完全由后端维护       ,格式正确可以事半功倍哦 let menuList = [ { "path": /home, "component": Layout, "redirect": "/list", "hidden": true, "children": [ { "path": "/list", "name": "List", "component": "index", "meta": { "icon": "monitor", "title": "xxxx" } }, { "path": "/shipInfo", "name": "ShipInfo", "component": "shipInfo", "meta": { "icon": "monitor", "title": "xxxx" } }, { "path": "/quality", "name": "Quality", "component": "qualityAssessment", "meta": { "icon": "monitor", "title": "xxxx" } }, ] } ] resolve(menuList); }) } // 模拟获取登录账号信息(用户登录       、获取权限) export function getInfo() { return new Promise((resolve, reject) => { const data = { code: 200, avatar: "xxxxxxxxxx", username: "nickName111", roles: [admin], permission: [允许操作], msg: "获取用户信息成功" } resolve(data); }) }

用vuex实现全局登录             、退出登录等方法

创建 store/modules/user.js            ,里面装载 用户登录                    、获取权限      、 退出登录清空权限       、存放token和权限菜单等全局变量和方法                   。在store/index.js引入

import { emergency } from @/api; import router from @/router; import { message } from ant-design-vue; import { getInfo } from @/api/menu const user= { state: { token: sessionStorage.token || , name: , avatar: , roles: [] }, mutations: { SET_TOKEN(state, token) { // console.log(state, token) state.token = token sessionStorage.setItem(token, state.token) }, SET_AVATAR(state, avatar) { state.avatar = avatar }, SET_NAME(state, name) { state.name = name }, SET_ROLES(state, roles) { state.roles = roles }, }, actions: { // 获取当前登录用户信息 login({ commit }, { params }) { // console.log(params) return new Promise((resolve, reject) => { emergency.login(params).then(res => { // console.log(res) const result = res.data commit(SET_TOKEN, result.token) resolve() }).catch(err => { reject(err) }) }) }, // 获取用户信息 //根据用户的token获取用户的个人信息                   ,里面包含了权限信息 getInfo({ commit }) { return new Promise((resolve, reject) => { getInfo().then(res => { // console.log(res) commit(SET_NAME, { name: res.name }) commit(SET_AVATAR, { headImgUrl: res.headImgUrl }) commit(SET_ROLES, { roles: res.roles }) resolve(res) }).catch(err => { reject(err) }) }) }, // 退出登录 userLogout ({ commit }) { // 清空权限菜单 commit(SET_ROLES, []) // 清空token commit(SET_TOKEN, ) // 跳转到登录菜单 router.push({path: /login}) } }, }; export default user;

在store/index.js引入

import user from ./modules/user Vue.use(Vuex) export default new Vuex.Store({ modules: { user, permission }, state: {}, mutations: {}, actions: {}, getters: { token: state => state.user.token, name: state => state.user.name, avatar: state => state.user.avatar, addRouters: state => state.permission.addRouters, roles: state => state.user.roles, } })

用vuex模块单独写权限路由的判断

创建 store/permission.js       , GenerateRoutes 方法判断获取有权限的路由      , hasPerMission 函数用于判断权限主要核心函数             。

import constantRoutes from ../../router/routes import { getRouters } from @/api/menu import Layout from @/components/layout const constantRouterComponents = { Layout } /** * 过滤账户是否拥有某一个权限                   ,并将菜单从加载列表移除 * * @param permission * @param route * @returns {boolean} */ function hasPermission(roles, route) { if (route.meta && route.meta.roles) { return roles.some(role => route.meta.roles.includes(role)) } else { return true } } // 遍历后台传来的路由字符串             ,转换为组件对象(过滤符合权限的路由) /** // 原方法 function filterAsyncRouter (routerMap, roles) { const accessedRouters = routerMap.filter(route => { if (hasPermission(roles, route)) { if (route.children && route.children.length) { route.children = filterAsyncRouter(route.children, roles) } return true } return false }) return accessedRouters } */ // 目前没有加入权限控制 filterAsyncRouter是修改过的 *需要的时候加上去即可* function filterAsyncRouter(asyncRouterMap) { const accessedRouters = asyncRouterMap.filter(route => { if (route.children && route.children.length) { route.children = filterAsyncRouter(route.children) } return true }) return accessedRouters } /** * 格式化树形结构数据 生成 vue-router 层级路由表 */ export const generator = (routerMap, parent) => { return routerMap.map(item => { const { title, icon } = item.meta || {} const currentRouter = { // 路由path      , path: item.path, // 路由名称                   ,建议唯一 name: item.name, // 该路由对应页面的 组件 component: (constantRouterComponents[item.component]) || (() => import(`@/views/${item.component}`)), // meta: 页面标题, 菜单图标 meta: { title: title, icon: icon || undefined, } } // 为了防止出现后端返回结果不规范             ,处理有可能出现拼接出两个 反斜杠 if (!currentRouter.path.startsWith(http)) { currentRouter.path = currentRouter.path.replace(//, /) } // 重定向 item.redirect && (currentRouter.redirect = item.redirect) // 是否有子菜单,并递归处理 if (item.children && item.children.length > 0) { // Recursion currentRouter.children = generator(item.children, currentRouter) } return currentRouter }) } const permission = { state: { routers: constantRoutes, addRouters: [] }, mutations: { SET_ROUTERS: (state, router) => { state.addRouters = router state.routers = constantRoutes.concat(router) } }, actions: { // 生成路由 GenerateRouters({ commit }, roles) { return new Promise(resolve => { getRouters().then(res => { const rdata = JSON.parse(JSON.stringify(res)) const routers = generator(rdata) const rewriteRoutes = filterAsyncRouter(routers) commit(SET_ROUTERS, rewriteRoutes) resolve(rewriteRoutes) }) }) }, } } export default permission;

监听路由跳转实现动态加载权限菜单

在src下创建permissionjs文件                   ,监听路由的跳转后                    ,在mainjs引入

判断是否 有token,没有则跳向登录页            ,

如果有token                    ,则进行用户权限获取 (在store/user下的getInfo函数)       ,

获取完权限进入 store/permission的GenerateRoutes函数 进行获取符合条件的路由            ,

再通过addRoute (addRoutes已经废弃)加载路由 // 先把路由和vuex引进来使用 import router from ./router import store from ./store import { resetRouter } from ./router/routes const whiteList = [/login] // 不重定向白名单 // console.log(store.getters.token) //路由拦截 router.beforeEach((to, from, next) => { if (store.getters.token) { // to.meta.title && store.dispatch(setTitle, to.meta.title) if (to.path === /login) { // next({ path: }) next() } else { // console.log(store.dispatch(GenerateRouters)) if (store.getters.roles.length === 0) { // 判断当前用户是否已拉取完userinfo信息 store.dispatch(getInfo).then((res) => { // console.log(res, userinfo信息) store.dispatch(GenerateRouters).then(accessRoutes => { // 根据roles权限生成可访问的路由表 // router.addRoutes()要使用addRoute 已经废弃 for (let x of accessRoutes) { // console.log(x) router.addRoute(x) } // router.addRoute(store.getters.addRouters) console.log(store.getters.addRouters) next({ ...to, replace: true }) // hack方法 确保addRoute已完成 }) }).catch(err => { //捕捉错误                   ,退出登录 // store.dispatch(LogOut).then(() => { // next({ path: / }) // }) }) next() } else { next() } } } else { // 没有token if (whiteList.indexOf(to.path) !== -1) { // 在免登录白名单       ,直接进入 next() } else { next(`/login`) // 否则全部重定向到登录页 } } }) 项目中没有注册路由会跳转到空白页      ,需要手动添加404页                   ,加在路由得最后

创心域SEO版权声明:以上内容作者已申请原创保护,未经允许不得转载,侵权必究!授权事宜、对本内容有异议或投诉,敬请联系网站管理员,我们将尽快回复您,谢谢合作!

展开全文READ MORE
python 编写工具(Python工具箱系列(二十)) 大学生炒股能赚多少(网上大学生如何赚钱-大学生炒股3个月赚10万,智商高炒股更容易赚钱么?)