vue权限路由详解

前言css


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

clipboard.png

启动node


mock项目:webpack

cd mock
npm install
npm start

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

项目目录git

clipboard.png

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

myProject项目:web

cd myProject
npm install
npm run dev

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

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

clipboard.png
这部分是webpack的代码分割,模块可按需加载,也就是懒加载,具体知识可点击连接进去查看。express

clipboard.png

不授权限控制的通用路由可定义在这里,直接在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,作状态管理,仍是很方便的。
这段代码流程:刷新或第一次访问项目的时候,会请求这个接口,
clipboard.png

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

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

clipboard.png

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...

相关文章
相关标签/搜索