vue-element-template 根据权限动态加载路由
vue-element-template 根据权限动态加载路由一、前序工作二、根据权限动态加载路由1.挂载前的验证2.保存一些相关信息3.获取用户角色4.筛选路由5最后的加载6效果截图三、遇到的bug1.data functions should return an object:2.动态路由显示不成功的原因四、结尾一、前序工作因为我是用template来开发的;想偷个懒,所以我去admin里拿了
vue-element-template 根据权限动态加载路由
一、前序工作
因为我是用template来开发的;所以简单了做了几个页面测试
在开始之前简单说一下vue-element-admin 的路由
它的路由有两种: 一种是通用页面路由constantRoutes;还有一种是动态路由 asyncRoutes
通用路由是可以直接挂载在页面的;不需要权限判断;我们要解决的是动态路由挂载
注意文件夹位置:src/router/index.js
添加asyncRoutes
export const asyncRoutes = [
{
path: '/permission',
component: Layout,
redirect: '/permission/test1',
alwaysShow: true, // will always show the root menu
name: 'Permission',
meta: {
title: 'Permission',
icon: 'lock',
roles: ['admin', 'editor'] // you can set roles in root nav
},
children: [
{
path: 'test1',
component: () => import('@/views/permission/test1'),
name: 'Test1',
meta: {
title: 'Permission test1',
roles: ['admin'] // or you can only set roles in sub nav
}
},
{
path: 'test2',
component: () => import('@/views/permission/test2'),
name: 'Test2',
meta: {
title: 'Permission test2',
roles: ['admin'] // or you can only set roles in sub nav
}
},
{
path: 'test3',
component: () => import('@/views/permission/test3'),
name: 'Test3',
meta: {
title: 'Permission test3'
// if do not set roles, means: this page does not require permission
}
}
]
},
// 404 page must be placed at the end !!!
{ path: '*', redirect: '/404', hidden: true }
]
二、根据权限动态加载路由
1.挂载前的验证
注意路径:src/permission.js
router.beforeEach(async(to, from, next) => {
// start progress bar
NProgress.start()
// set page title
document.title = getPageTitle(to.meta.title)
// determine whether the user has logged in
const hasToken = getToken()
// 判断是否存在token,没有就重新登陆
if (hasToken) {
if (to.path === '/login') {
// if is logged in, redirect to the home page
next({ path: '/' })
NProgress.done()
} else {
// determine whether the user has obtained his permission roles through getInfo
const hasRoles = store.getters.roles && store.getters.roles.length > 0//这里指的是src/store/getters.js的roles
console.log(hasRoles)
//判断是否已经有roles了
if (hasRoles) {
next()
} else {
try {
// get user info
// note: roles must be a object array! such as: ['admin'] or ,['developer','editor']
//获取roles
const { roles } = await store.dispatch('user/getInfo')//第一步
// generate accessible routes map based on roles
//获取通过权限验证的路由
const accessRoutes = await store.dispatch('permission/generateRoutes', roles)//第二步
//更新加载路由
router.options.routes = store.getters.permission_routes//第三步
// dynamically add accessible routes
router.addRoutes(accessRoutes)
console.log(store)
// hack method to ensure that addRoutes is complete
// set the replace: true, so the navigation will not leave a history record
next({ ...to, replace: true })
} 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()
}
}
}
} 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()
}
}
})
这里分了核心三步,第一步获取用户个人信息(角色);第二部筛选用户可以看见的路由;第三步更新加载路由
2.保存一些相关信息
注意路径:src/store/modules/user.js
注意roles和SET_ROLES是必须的
const getDefaultState = () => {
return {
token: getToken(),
name: '',
avatar: '',
introduction: '',
roles: []
}
}
const state = getDefaultState()
const mutations = {
RESET_STATE: (state) => {
Object.assign(state, getDefaultState())
},
SET_TOKEN: (state, token) => {
state.token = token
},
SET_INTRODUCTION: (state, introduction) => {
state.introduction = introduction
},
SET_NAME: (state, name) => {
state.name = name
},
SET_AVATAR: (state, avatar) => {
state.avatar = avatar
},
SET_ROLES: (state, roles) => {
state.roles = roles
}
}
3.获取用户角色
注意路径:src/store/modules/user.js
// get user info
getInfo({ commit, state }) {
return new Promise((resolve, reject) => {
//我这里用的是post请求获取个人信息
getInfo({ token: state.token }).then(response => {
//注意这个data,有一些初学者或者粗心的人会被这里卡一下这里涉及到es6的解构函数;
const { data } = response
if (!data) {
reject('Verification failed, please Login again.')
}
//返回的info最少需要包含以下内容(角色,名称,头像,简介)个人需求
//大家可以只返回roles就行了
const { roles, name, avatar, introduction } = data
if (!roles || roles.length <= 0) {
reject('getInfo: roles must be a non-null array!')
}
console.log(roles)
//存起来
commit('SET_ROLES', roles)
commit('SET_NAME', name)
commit('SET_AVATAR', avatar)
commit('SET_INTRODUCTION', introduction)
resolve(data)
}).catch(error => {
reject(error)
})
})
},
注意路径:src/store/getters.js
4.筛选路由
注意路径:src/store/modules/permission.js
直接把vue-element-admin的这个页面复制下来就好了
import { asyncRoutes, constantRoutes } from '@/router'
/**
* Use meta.role to determine if the current user has permission
* @param roles
* @param route
*/
//匹配权限
function hasPermission(roles, route) {
if (route.meta && route.meta.roles) {
return roles.some(role => route.meta.roles.includes(role))
} 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: [],
addRoutes: []
}
const mutations = {
SET_ROUTES: (state, routes) => {
state.addRoutes = routes
state.routes = constantRoutes.concat(routes) // 将过滤后的路由和constantRoutes存起来
}
}
//筛选
const actions = {
generateRoutes({ commit }, roles) {
return new Promise(resolve => {
let accessedRoutes
//路由是否有admin,有直接全部显示
if (roles.includes('admin')) {
accessedRoutes = asyncRoutes || []
} else {
//过滤路由
accessedRoutes = filterAsyncRoutes(asyncRoutes, roles)
//accessedRoutes这个就是当前角色可见的动态路由
}
commit('SET_ROUTES', accessedRoutes)
resolve(accessedRoutes)
})
}
}
export default {
namespaced: true,
state,
mutations,
actions
}
5最后的加载
这就是之前的第三步
router.options.routes = store.getters.permission_routes
很多人直接用router.addRoutes(accessRoutes)
发现无法更新路由,但是路由是被定义了的;后面看文档,是因为Router的路由并不是响应式的,所以只能读取到初始路由。然后要在router.addRoutes(accessRoutes)
,加上那句话就可以了
或者参考一下大佬的加载方法
手摸手,带你用vue撸后台 系列二(登录权限篇)
6效果截图
三、遇到的bug
1.data functions should return an object:
这个问题是返回的内容格式不对;报错的地方是 src/permission.js
2.动态路由显示不成功的原因
1.有可能是没有更新出来;就如同我的2.5小结,Router的路由并不是响应式的,所以只能读取到初始路由;所以显示不出来
2. 这个路由必须放在最后{ path: '*', redirect: '/404', hidden: true }
,因为path:’*’ 代表所有路由;如果放在前面会卡住后面的路由,导致显示失败
四、结尾
因为是本人的实践所得;如果有什么错误或者不足指出之处请指出,我会立马改正
参考了大佬的文章
手摸手,带你用vue撸后台 系列二(登录权限篇)
更多推荐
所有评论(0)