Vue + element UI 动态路由生成侧边栏的权限

第一次做项目的权限问题时,也是第一次做,主要参考了花裤衩大神的手摸手博文以及百度的一些,综合自己的情况做出来了,实属不易,第一次做,下面正式开始

       首先后台会给你一个权限列表的json数组,他也许会放在个人信息接口,也可以单独放一个接口,都是一样的,只是我们前端获取的方式不同,我做的这个是分开放的,在api放入你的后台接口,像这样Vue + element UI 动态路由生成侧边栏的权限_第1张图片

然后在/src/store/modules/user.js文件调用此接口,该文件存放的是改用户登录,登出,个人信息等的接口,存放在store,方便全局调用

Vue + element UI 动态路由生成侧边栏的权限_第2张图片

我们下一步就去src/permission.js文件调用此方法(和main.js同级)解释在代码中注释了,不懂得可以看注释

import router from './router'
import store from './store'
import { Message } from 'element-ui'
import NProgress from 'nprogress' // progress bar
import 'nprogress/nprogress.css' // progress bar style
import { getToken } from '@/utils/auth' // get token from cookie
import getPageTitle from '@/utils/get-page-title'

// NProgress.configure({ showSpinner: false }) // NProgress Configuration

// 用来控制按钮的显示
export function hasBtnPermission (permission) {
  const myBtns = store.getters.buttons
  return myBtns.indexOf(permission) > -1
}

const whiteList = ['/login', '404'] //  白名单路由
// 路由处理--登录验证
// beforeEach() 路由守卫,在跳转之前执行
router.beforeEach(async (to, from, next) => {
  // to: Route: 即将要进入的目标 路由对象
  // from: Route: 当前导航正要离开的路由
  // next: Function: 一定要调用该方法来 resolve 这个钩子。执行效果依赖 next 方法的调用参数。
  // 开始进度条
  // NProgress.start()
  // 设置页面标题
  document.title = getPageTitle(to.meta.title)
  const hasToken = getToken()
  // 判断是否登录时,因为页面刷新后内存中还没有token信息,额外从session中判断一次
  if (hasToken) {
    if (to.path === '/login') {
      // 已经登录的,不能跳到登陆页面,跳到首页
      next({ path: '/' })
      // NProgress.done()
    } else {
      const hasGetUserInfo = store.getters.name
      if (hasGetUserInfo) {
        next()
      } else {
        let userInfo = store.state.user.name
        if (!userInfo) {
          try {
            // if (store.getters.roles.length === 0) { // 判断当前用户是否已拉取完user_info信息
            store.dispatch('user/getInfo') // 获取用户信息
            await store.dispatch('user/getMenu').then(res => { // 拉取权限菜单
              let roles = res
              store.dispatch('permission/GenerateRoutes', { roles }).then(() => { // 生成可访问的路由表
                router.addRoutes(store.getters.addRouters) // 动态添加可访问路由表
                // next({ ...to, replace: true }) // hack方法 确保addRoutes已完成 ,//菜单权限更新完成,重新进一次当前路由
                next(store.getters.addRouters[0]) // hack方法 确保addRoutes已完成 ,//菜单权限更新完成,重新进一次第一个路由
                router.options.routes = store.getters.routes  // 渲染侧边栏需要用到
              })
              // })
            }).catch(err => {
              console.log(err)
            })
          } catch (error) {
            // remove token and go to login page to re-login
            // await store.dispatch('user/resetToken')
            // Message.error(error || 'Has Error')
            // next(`/login?redirect=${to.path}`)
            // NProgress.done()
            if (whiteList.indexOf(to.path) !== -1) { // 在免登录白名单,直接进入
              next()
            } else {
              next('/login')
            }
          }
        } else {
          if (to.path === '/login') {
            next({ name: 'Dashboard' })
          } else {
            if (hasPermission(to, store.getters.accessMenu)) {
              Util.toDefaultPage(store.getters.accessMenu, to, routes, next);
            } else {
              next({ path: '/403', replace: true })
            }
          }
        }
      }
    }
  } else {
    /* has no token*/
    if (whiteList.indexOf(to.path) !== -1) {
      // in the free login whitelist, go directly
      next()
    } else {
      // other pages that do not have permission to access are redirected to the login page.
      next(`/login?redirect=${to.path}`)
      // NProgress.done()
    }
  }
})
router.afterEach(() => {
  // finish progress bar
  // NProgress.done()
})

store.dispatch('user/getInfo')和store.dispatch('user/getMenu')是在上面讲的调用接口的文件的方法,  store.dispatch('permission/GenerateRoutes', { roles })这个也是一样的,这个是在/src/store/modules/permission.js里,下面讲这个文件,这个文件最为重要,所有操作都在这里,重点来了!!!!!!!!

import { asyncRoutes, constantRoutes } from '@/router'

/**
 * Use meta.role to determine if the current user has permission
 * @param roles
 * @param route
 * roles 是用户的权限表
 * route 就是对应的路由配置中的路由对象
 */
// 原来的方法 
// function hasPermission(roles, route) {
// if (route.meta && route.meta.roles) {
//   return roles.some(role => route.meta.roles.includes(role))
//  } else {
//    return true
//   }
// }

// 根据自己的情况做判断的方法
function hasPermission (roles, route) {
  if (route.meta && route.meta.permission) {
    // some循环 当内部return true时跳出整个循环
    return roles.some(role => route.meta.permission.includes(role.permission))
  } else {
    return true
  }
}
/**
 * Filter asynchronous routing tables by recursion
 * @param routes asyncRoutes
 * @param roles
 */
export function filterAsyncRoutes (routes, roles) {
  const res = []
  routes.forEach(route => {
    const tmp = { ...route }
    if (hasPermission(roles, tmp)) {
      if (tmp.children) {
        tmp.children = filterAsyncRoutes(tmp.children, roles)
      }
      res.push(tmp)
    }
  })

  return res
}
const state = {
  routes: [],  // 和左侧绑定的路由数组表
  addRouters: []
}

const mutations = {
  SET_ROUTES: (state, routes) => {
    state.addRouters = routes
    state.routes = constantRoutes.concat(routes)
  }
}
const actions = { // roles是用户所带的权限 GenerateRoutes()用于生成当前用户可以访问的路由
  GenerateRoutes ({ commit }, data) {
    return new Promise(resolve => {
      const { roles } = data
      let accessedRoutes
      if (roles.includes('admin')) {
        accessedRoutes = asyncRoutes || []
      } else {
        accessedRoutes = filterAsyncRoutes(asyncRoutes, roles)
      }
      commit('SET_ROUTES', accessedRoutes)
      resolve(accessedRoutes)
    })
  }
}

export default {
  namespaced: true,
  state,
  mutations,
  actions
}

constantRoutes 静态路由(不需要权限的路由),asyncRoutes 动态路由(需要权限的路由)

hasPermission()方法是用来判断后台给的和你自己本地的是否能匹配的 ,我的是和后台商量好,用meta.permission来做判断,在src\router\index.js 存放所有路由的地方Vue + element UI 动态路由生成侧边栏的权限_第3张图片

 permission: ['member:add']是和后台商量一起用的,后台返回member:add这个字段,我就用此字段和我本地路由做匹配,匹配出来就把他添加到动态路由accessedRoutes。

GenerateRoutes方法也就是在上面调用的方法,到此已经拿到了,找到侧边栏渲染出来即可,在src\layout\components\Sidebar\index.vue

Vue + element UI 动态路由生成侧边栏的权限_第4张图片

Vue + element UI 动态路由生成侧边栏的权限_第5张图片

从vuex用映射的方式获取到权限侧边栏列表数组,this.$router.options.routes此来源看src/permission.js文件,到此就结束了,还有按钮的权限,下一篇见

你可能感兴趣的:(vue.js,javascript,es6)