美文网首页
VUE 动态菜单及视图权限

VUE 动态菜单及视图权限

作者: yoolika | 来源:发表于2019-01-21 16:26 被阅读0次

    动态菜单

    这几天在做VUE的动态菜单及权限,参考了下:

    https://segmentfault.com/a/1190000015419713?utm_source=tag-newest

    然后发现和我的需求还是有点不符:上面的作者是整个权限都是从接口拉下来的
    而我的需求是:原来有一部分权限,然后从接口获取另外一部分权限,PUSH到现有权限中
    所以对作者的GIT代码进行了修改,原来的权限:

    const vueRouter = new Router({
      routes: [
        {
          path: '/',
          name: 'login',
          component: Login
        },
        {
          path: '/login',
          name: 'login',
          component: Login
        },
        {
          path: '*',
          component: error404
        },
        {
          path: '/manage',
          name: '首页',
          component: Manage,
          meta: { title: '首页' },
          children: [
              {
              path: 'home',
              component: Home,
              meta: { title: '首页' }
            }
          ]
        },
        {
          path: '/404',
          name: '出错了',
          component: error404
        }
      ]
      //路由样式
      // linkActiveClass: "active-router",
      // linkExactActiveClass: "exact-router"
    })
    

    主要修改的是permission.js

    import router from './router'
    import store from './store'
    // import { Message } from 'element-ui'
    import axios from 'axios'
    const _import = require('@/router/_import_' + process.env.NODE_ENV)//获取组件的方法
    import Layout from '@/page/manage' //Layout 是架构组件,不在后台返回,在文件里单独引入
    import { getToken } from '@/utils/auth' // getToken from cookie
    
    
    router.beforeEach((to, from, next) => {
      console.log("====beforeEach====")
      if (getToken()) { //如果用户已经登录
        if (to.path === '/login') {
          next()
          // NProgress.done() // if current page is dashboard will not trigger  afterEach hook, so manually handle it
        } else {
          if (store.getters.getMenu.length === 0) {
            store.dispatch('GetUserInfo').then(res => {
              var getRouter = res.data.router//后台拿到路由
              routerGo(to, next, getRouter)//执行路由跳转方法
            }).catch((err) => {
              store.dispatch('FedLogOut').then(() => {
                // Message.error(err || 'Verification failed, please login again')
                console.log(err)
                next({ path: '/login' })
              })
            })
          } else {
            next();
            }
          }
        }
      } else {
        if (to.path == '/login') {//如果是登录页面路径,就直接next()
          next();
        } else {//不然就跳转到登录;
          next('/login');
        }
      }
    })
    
    
    function routerGo(to, next, getRouter) {
      getRouter = filterAsyncRouter(getRouter) //过滤路由
      getRouter.map(v => { router.options.routes.push(v) })//将接口获取到的路由push到现有路由中
      router.addRoutes(getRouter)//动态添加路由
      global.antRouter = router.options.routes //将路由数据传递给全局变量,做侧边栏菜单渲染工作
      next({ ...to, replace: true }) // hack方法 确保addRoutes已完成 ,set the replace:
    }
    
    function filterAsyncRouter(asyncRouterMap = []) { //遍历后台传来的路由字符串,转换为组件对象
      const accessedRouters = asyncRouterMap.filter(route => {
        if (route.component) {
          if (route.component === 'Layout') {//Layout组件特殊处理
            route.component = Layout
          } else {
            route.component = _import(route.component)
          }
        }
        if (route.children && route.children.length) {
          route.children = filterAsyncRouter(route.children)
        }
        return true
      })
    
      return accessedRouters
    }
    

    关键是这句getRouter.map(v => { router.options.routes.push(v) })//将接口获取到的路由push到现有路由中
    如果你想加入到现有router的某个节点的children里 可以这样:
    router.options.routes[0].children.push()
    这里还要注意的是 beforeEach会出现死循环
    因为next({ path: '/login' })next方法加了参数 就又会走一次beforeEach方法 如果是next()就不会
    可以这样处理:

    if (to.path == '/login') {//如果是登录页面路径,就直接next()
          next();
        } else {//不然就跳转到登录;
          next('/login');
        }
    

    视图权限

    也就是按钮级别的权限。原理很简单,利用router的meta字段

    {
            "path": "/system",
            "component": "Layout",
            "redirect": "/system/userList",
            "name": "系统管理",
            "meta": {
              "title": "系统管理",
              "icon": "el-icon-setting"
            },
            "children": [{
              "path": "userList",
              "name": "用户列表",
              "component": "user/index",
              "meta": {
                "title": "用户列表",
                "icon": "el-icon-tickets",
                "permission": ['add'] //按钮权限
              }
            }
      ]
    }
    

    meta.permission字段里放入的是该用户在此页面能操作的按钮权限的标识,比如这个页面有add、edit、delele权限,但是你只想让这个用户使用add,那么就"permission": ['add']

    接着自定义指令btnPermission.js,在mian.js导入

    import Vue from 'vue'
    
    /**权限指令**/
    Vue.directive('has', {
        inserted: function (el, binding, vnode) {
            let permissionList = vnode.context.$route.meta.permission;
            if (!permissionList || !permissionList.includes(binding.value.role)) {
                el.parentNode.removeChild(el)
            }
        }
    })
    export { has }
    

    如何使用:

    <el-button type="success" icon="el-icon-circle-plus-outline" @click="handeleAdd" v-has="{role : 'add'}">添加</el-button>
    

    这里要注意vue2.0 自定义指令 v-has="{role : 'add'}"参数必须要传入对象 否则会无效

    具体代码我上传到了GIT:https://github.com/yoolika/admin-manage

    相关文章

      网友评论

          本文标题:VUE 动态菜单及视图权限

          本文链接:https://www.haomeiwen.com/subject/nlbcjqtx.html