vue权限路由详解

前言

近期,用vue框架做了个后台管理项目,涉及权限,参考网上资料,得此项目https://github.com/zhangxuexi…
不知大家是否还是各种mock工具来模拟数据,此项目,包含一个基于express,搭建的mock模拟服务,个人觉得,高大上了一点有木有!

《vue权限路由详解》

启动

mock项目:


cd mock
npm install
npm start

基于node.js的mock服务就启动起来了。

项目目录

《vue权限路由详解》

请求接口路由都在这个routes/index.js里定义,接口返回的都是写死的json数据。如需连接数据库等操作请自行百度。这个项目不作重点介绍

myProject项目:


cd myProject
npm install
npm run dev

两个项目分别启动起来后,可用下面账号登录:
角色1:用户名:123 密码:a123456
角色2:用户名:456 密码:a123456

router.js 权限路由
重点来了,直接上干货!

《vue权限路由详解》
这部分是webpack的代码分割,模块可按需加载,也就是懒加载,具体知识可点击链接进去查看。

《vue权限路由详解》

不受权限控制的通用路由可定义在这里,直接在vue实例中注入即可。

export const asyncRoutes = [
  {
    path: 'home',
    component: home,
    redirect: '/home/index',
    meta: {role: ['0', '1'], nav: false},
    children:
      [
        {
          path: '/home/index',
          name: '概览',
          component: companyIndex,
          meta: { role: ['1'], nav: true }
        },
        {
          path: '/home/index',
          name: '概览',
          component: userIndex,
          meta: { role: ['0'], nav: true }
        },
        {
          path: '/policy',
          name: '列表管理',
          component: policy,
          redirect: '/policy/list',
          meta: { role: ['0'], nav: true },
          children: [
            {
              path: 'list',
              name: '列表',
              component: userList,
              meta: { role: ['0'], nav: true }
            }
          ]},
        {
          path: '/policy',
          name: '列表管理',
          component: policy,
          redirect: '/policy/company',
          meta: { role: ['1'], nav: true },
          children: [
            {
              path: '/policy/company',
              name: '列表',
              redirect: '/policy/company/list',
              component: policy,
              meta: { role: ['1'], nav: true },
              children: [
                {
                  path: 'list',
                  name: '列表',
                  component: companyList,
                  meta: { role: ['1'], nav: false }
                },
                {
                  path: 'detail/:policyNum',
                  name: '列表详情',
                  component: detailCompany,
                  meta: { role: ['1'], nav: false }
                },
                {
                  path: 'add',
                  name: '添加',
                  component: addCompany,
                  meta: { role: ['1'], nav: false }
                }
              ]}
          ]
        }
      ]
  }
]

这部分是权限路由,以每个路由记录的元信息字段,定义权限。

meta:{role:['0'], nav:true}

role:代表这条路由记录的所属角色,nav:true代表要显示在导航栏,例如一些列表路由,false:代表不显示在导航栏,例如添加,查看路由。

router.beforeEach((to, from, next) => {
  // 第一步 先去vuex拉取用户信息
  let info = store.state.userInfo
  let infoLength = Object.keys(info).length === 0
  // infoLength为true 说明是第一次访问系统或者刷新页面,在这里判断路由'/login',防止进入死循环。未登录,status为1,跳到登录页面,已登录,status为0,继续访问页面
  if (infoLength && to.path !== '/login' && to.path !== '/forget') {
    store.dispatch('getUserInfo').then((response) => {
      if (response.status === '0') {
        store.dispatch('userLogin', response.data) // 将用户基本信息存入vuex
        store.dispatch('permission', response.data.userType).then(() => { // 根据用户角色,动态添加权限路由
          router.addRoutes(store.state.navList)
          next({ ...to, replace: true })
        }
        )
      } else if (response.status === '1') {
        next('/login')
      } else if (response.status === '2') { // 刷新时登录失效
        next() // 刷新后 加载出原页面再提示登录失效,防止出现空白页面
        Message({
          message: '登录失效,请重新登录',
          type: 'error',
          duration: 2000,
          showClose: true,
          customClass: 'my-el-message',
          onClose: function () {
            next('/login')
          }
        })
      }
    })
  } else { // infoLength为false 说明是静态点击,不需要任何操作
    next()
  }
})

代码注释写的很详细了,这里用了vuex,做状态管理,还是很方便的。
这段代码流程:刷新或第一次访问项目的时候,会请求这个接口,
《vue权限路由详解》

如果接口返回正确数据,说明是已登录,继续跳转路由
如果未返回正确数据,则跳回登录路由。

接口返回正确数据后,根据权限,去筛选路由

《vue权限路由详解》

vuex:permission详情

import { asyncRoutes } from '@/router/index'
import { getUserInfo } from '@/common/getUser'
const actions = {
  userLogin: ({commit}, userData) => commit('userLogin', userData), /* 用户信息存储 */
  permission: ({commit}, role) => { /* 根据权限信息加载权限路由 */
    let routeArr = deepCopy(asyncRoutes) // 含有复杂数组对象,循环进行深拷贝
    const b = filterAsyncRouter(routeArr, role)
    commit('navList', b)
  },
  getUserInfo: ({commit}) => { // 检验是否登录请求
    return getUserInfo()
  }
}
// 根据权限 筛选路由
function filterAsyncRouter (asyncRouterMap, roles) {
  const accessedRouters = asyncRouterMap.filter(route => {
    if (route.meta.role.indexOf(roles) >= 0) {
      if (route.children && route.children.length) {
        route.children = filterAsyncRouter(route.children, roles)
      }
      return true
    }
    return false
  })
  return accessedRouters
}
function deepCopy (routeArr) {
  return routeArr.map((arr) => {
    arr = Object.assign({}, arr)
    return arr
  })
}

export default actions

针对刷新时,vuex中数据丢失,这里,没有使用localstorge或者sessionstorge做缓存,主要考虑这两种缓存方式的缺点均不符合公司业务要求,localstorge:手动清除才能消失,sessionstorge:只在本标签页有效。

不如直接来个接口,让后端判断登录时效来的更安全。

好了,关于路由的就分析到这里,大家理解了吗?欢迎大家star哈
https://github.com/zhangxuexi…

    原文作者:yedu
    原文地址: https://segmentfault.com/a/1190000015451081
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞