前言
近期,用vue框架做了个后台管理项目,涉及权限,参考网上资料,得此项目https://github.com/zhangxuexi...。
不知大家是否还是各种mock工具来模拟数据,此项目,包含一个基于express,搭建的mock模拟服务,个人觉得,高大上了一点有木有!
启动
mock项目:
cd mock
npm install
npm start
基于node.js的mock服务就启动起来了。
项目目录
请求接口路由都在这个routes/index.js里定义,接口返回的都是写死的json数据。如需连接数据库等操作请自行百度。这个项目不作重点介绍
myProject项目:
cd myProject
npm install
npm run dev
两个项目分别启动起来后,可用下面账号登录:
角色1:用户名:123 密码:a123456
角色2:用户名:456 密码:a123456
router.js 权限路由
重点来了,直接上干货!
这部分是webpack的代码分割,模块可按需加载,也就是懒加载,具体知识可点击链接进去查看。
不受权限控制的通用路由可定义在这里,直接在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...
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。