前言css
近期,用vue框架作了个后台管理项目,涉及权限,参考网上资料,得此项目https://github.com/zhangxuexi...。
不知你们是否仍是各类mock工具来模拟数据,此项目,包含一个基于express,搭建的mock模拟服务,我的以为,高大上了一点有木有!vue
启动node
mock项目:webpack
cd mock npm install npm start 基于node.js的mock服务就启动起来了。
项目目录git
请求接口路由都在这个routes/index.js里定义,接口返回的都是写死的json数据。如需链接数据库等操做请自行百度。这个项目不做重点介绍github
myProject项目:web
cd myProject npm install npm run dev
两个项目分别启动起来后,可用下面帐号登陆:
角色1:用户名:123 密码:a123456
角色2:用户名:456 密码:a123456vuex
router.js 权限路由
重点来了,直接上干货!数据库
这部分是webpack的代码分割,模块可按需加载,也就是懒加载,具体知识可点击连接进去查看。express
不授权限控制的通用路由可定义在这里,直接在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,作状态管理,仍是很方便的。
这段代码流程:刷新或第一次访问项目的时候,会请求这个接口,,
若是接口返回正确数据,说明是已登陆,继续跳转路由
若是未返回正确数据,则跳回登陆路由。
接口返回正确数据后,根据权限,去筛选路由
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...