博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
addRoutes实现动态权限路由菜单
阅读量:5942 次
发布时间:2019-06-19

本文共 5023 字,大约阅读时间需要 16 分钟。

需求

最近接手一个后台管理系统,需要实现导航菜单从后台拉取的效果;根据登录用户的权限不同分别拉出来的导航菜单也不一样,另外可操作的界面也存在区别。

问题

因为后台管理系统是准备使用vue+vue-router+element-ui+vuex的搭配来做的,可是单页应用在进入页面之前就已经将vue-router实例化并且注入vue实例中了,所以在进入登录页面的时候旧没办法在重新定制路由了。接下来各种百之谷之,发现vue-router在2.0版本中提供了addRoutes方法添加路由,希望的曙光出现。

经过一番折腾终于实现了功能,记录下来便于回顾,也希望能帮助到同样有需求的同志。

思路

1、首先在本地配置好固定不变的路由地址,例如登录,404这些页面,如下:

import Vue from 'vue'import Router from 'vue-router'import store from '@/vuex/store'Vue.use(Router)let router = new Router({  routes: [    {      path: '/login',      name: 'login',      meta: {requireAuth: false},      // 模块使用异步加载      component: (resolve) => require(['../components/login/login.vue'], resolve)    }]})// 拦截登录,token验证router.beforeEach((to, from, next) => {  if (to.meta.requireAuth === undefined) {    if (store.state.token) {      next()    } else {      next({        path: '/login'      })    }  } else {    next()  }})export default router

配置好这些固定的路由后我们才能够到登录页面,不然是无法继续下去的。

2、然后重要的一步,我们需要跟后端老铁约定好需要返回的权限菜单列表信息;首先这里我们先分析一下自己需要的路由结构,这里以我自己的路由作为例子。如果是我自己直接定义路由的话,会是以下结构:

let router = new Router({  routes: [    {      path: '/login',      name: 'login',      meta: {requireAuth: false},      component: (resolve) => require(['../components/login/login.vue'], resolve)    },    {        path: '/',        redirect: '/layout'    },    {        path: '/layout',        component: (resolve) => require(['../layout.vue'], resolve),        children: [            {                path: 'index',                 meta: {                    type: '1',       //控制是否显示隐藏 1显示,2隐藏                    code: 00010001,  // 后面需要控制路由高亮                    title: '首页',    // 菜单名称                    permissonList: [] // 权限列表                }                component: (resolve) => require(['@/components/index/index.vue'], resolve)            },            {            ...            }              ]    }]})

根据以上结构分析,其实真正需要动态配置的路由其实是/layout下面的children部分,所以需要后端返回给我们包含所有路由的一个数组就可以了

clipboard.png

返回的数据中rootList中是一级导航的列表,一级导航实际是没有路由功能,只是作为切换二级菜单的触发器,subList才是我们真正需要的路由信息。
3、拿到权限路由信息后,需要我们在本地对数据进行处理组装成我们需要的数据:

// 登录      login () {        let params = {          account: this.loginForm.username,          password: encrypt(this.loginForm.password)        }        this.loading = true        this.$http.post(this.$bumng + '/login', this.$HP(params))          .then((res) => {            this.loging = false            console.info('菜单列表:', res)            if (res.resultCode === this.$state_ok) {              // 合并一级菜单和二级菜单,便于显示              let menus = handleMenu.mergeSubInRoot(res.rootList, res.subList)              // 本地化处理好的菜单列表              this.saveRes({label: 'menuList', value: menus})              // 根据subList处理路由              let routes = handleMenu.mergeRoutes(res.subList)              // 本地化subList,便于在刷新页面的时候重新配置路由              this.saveRes({label: 'subList', value: res.subList})              // 防止重复配置相同路由              if (this.$router.options.routes.length <= 1) {                this.$router.addRoutes(routes)                // this.$router不是响应式的,所以手动将路由元注入路由对象                this.$router.options.routes.push(routes)              }              this.$router.replace('/layout/index')            }          })          .catch((err) => {            this.loging = false            console.error('错误:', err)          })      },

处理菜单列表和subList的方法:mergeSubInRoot 和 mergeRoutes

const routes = [  {    path: '/',    redirect: '/layout'  },  {    path: '/layout',    component: (resolve) => require(['../layout.vue'], resolve),    children: []  }]export default {  /**   * 合并主菜单和子菜单   * @param: rootList [Array] 主菜单列表   * @param: subList [Array] 子菜单   * */  mergeSubInRoot (roots, subs) {    if (roots && subs) {      for (let i = 0; i < roots.length; i++) {        let rootCode = roots[i].code        roots[i].children = []        for (let j = 0; j < subs.length; j++) {          if (rootCode === subs[j].code.substring(0, 4)) {            roots[i].children.push(subs[j])          }        }      }    }    return roots  },  /**   * 合并远程路由到本地路由   * @param: subList [Array] 远程路由列表   * @param: routes [Array] 本地路由列表   * */  mergeRoutes (subs) {    if (subs) {      for (let i = 0; i < subs.length; i++) {        let temp = {          path: subs[i].actUrl,          name: subs[i].actUrl,          component: (resolve) => require([`@/components/${subs[i].component}.vue`], resolve),          meta: {            type: subs[i].type,            code: subs[i].code,            title: subs[i].name,            permissionList: subs[i].permissionList          }        }        routes[1].children.push(temp)      }    }    return routes  }}

至此我们已经将权限路由成功配置进本地路由了,我的系统登录进入如下

clipboard.png

后续优化

1、菜单列表的显示以及二级导航切换:

2、防止刷新路由丢失;由于在刷新的时候单页应用会重新初始化,这时候所有配置的路由都会丢失,一朝回到解放前,只有本地配置的路由能够跳转。这时候我们可以在app.vue(ps:不论在哪里进行刷新,app.vue都会执行)中执行如下代码:

这样即使刷新,也会重新配置路由了。

3、关于页面按钮级别控制,可以自定义一个指令,去做这件事情。因为我们已经权限列表放入了相应路由的meta对象中,所以我们可以很方便的在每个页面回去到当前用户在当前页面所拥有的权限

clipboard.png

参考官方文档

结语

打完收工,得亏vue-router2中添加了addRoutes的方法,不然

转载地址:http://vuzxx.baihongyu.com/

你可能感兴趣的文章
iis6 zencart1.39 伪静态规则
查看>>
SQL Server代理(3/12):代理警报和操作员
查看>>
基于事件驱动的DDD领域驱动设计框架分享(附源代码)
查看>>
Linux备份ifcfg-eth0文件导致的网络故障问题
查看>>
2018年尾总结——稳中成长
查看>>
JFreeChart开发_用JFreeChart增强JSP报表的用户体验
查看>>
度量时间差
查看>>
通过jsp请求Servlet来操作HBASE
查看>>
crontab执行shell脚本日志中出现乱码
查看>>
Shell编程基础
查看>>
Shell之Sed常用用法
查看>>
3.1
查看>>
校验表单如何摆脱 if else ?
查看>>
JS敏感信息泄露:不容忽视的WEB漏洞
查看>>
分布式memcached服务器代理magent安装配置(CentOS6.6)
查看>>
Create Volume 操作(Part III) - 每天5分钟玩转 OpenStack(52)
查看>>
tomcat 8.0虚拟机配置文档
查看>>
pxc群集搭建
查看>>
JS中加载cssText延时
查看>>
常用的脚本编程知识点
查看>>