需求:后端根据角色使用路由权限,返回路由表给前端,前端比对路由表筛选匹配路由并添加
- 用户登录拿到路由表
LoginByUsername({ commit }, userInfo) {
return new Promise((resolve, reject) => {
apis
.loginByUsername(userInfo)
.then((response) => {
const data = response
// 模拟后端暂时未设置权限路由,返回的权限菜单
!data.jurisdiction.length && (data.jurisdiction = [
{ name: '系统概述', children: [] },
{
name: '品牌管理',
children: [
{ name: '平台账号管理', children: [] },
{ name: '人员限制', children: [] },
{ name: '组织管理', children: [] },
{ name: '门店管理', children: [] }
]
}
])
commit('SET_USERINFO', data)
resolve()
})
.catch((error) => {
reject(error)
})
})
},
// mutations
SET_JURISDICTION: (state, jurisdiction) => {
state.jurisdiction = jurisdiction
},
// 返回的菜单与侧边栏总菜单比对,并返回相同的路由菜单
SET_ADDJURISDICTION: (state, Jurisdiction) => {
// recursionRouter 为比对方法,已封装
layout.children = recursionRouter(Jurisdiction, layout.children)
state.addJurisdiction = layout.children
router.addRoute(layout) // 动态添加可访问路由表
// 404页面最后添加
router.addRoute({
path: '*',
redirect: '/404'
})
// 视图非同步更新,添加此代码可查看添加路由情况
router.options.routes.push(layout)
// 旧版添加路由main需为一个数组里面包裹对象
router.addRoutes(main) // 动态添加可访问路由表
},
SET_USERINFO: (state, userInfo) => {
state.userInfo = userInfo
localStorage.setItem('userInfo', JSON.stringify(userInfo))
}
// actions得addJurisdiction方法
addJurisdiction({ commit }, addJurisdiction) {
return new Promise((resolve) => {
// 比对路由表并添加权限路由
commit('SET_ADDJURISDICTION', addJurisdiction)
// 保存后端给的数据
commit('SET_JURISDICTION', addJurisdiction)
resolve()
})
}
// 引入的layout页面代码
const layout = {
path: '/layout',
name: 'Layout',
component: () => import(/* webpackChunkName: "layout" */ 'views/layout/index.vue'),
redirect: '/system',
hidden: true,
children: [...System, ...BrandManagement, ...ExceptionMonitoring, ...DailyRecord, ...SuperAdmin]
}
export default layout
// recursionRouter方法
// userRouter:后端传递得表, allRouter:前端路由表
export function recursionRouter(userRouter = [], allRouter = []) {
var realRoutes = []
allRouter.forEach((v, i) => {
userRouter.forEach((item, index) => {
if (item.name === v.meta?.title) {
if (item.children && item.children.length > 0) {
v.children = recursionRouter(item.children, v.children)
}
realRoutes.push(v)
}
})
})
return realRoutes
}
- 在main.js引入文件permission.js 在路由进入之前作权限分析
// permission.js文件
// 由于项目未完全搭建完成,部分判断非最终代码
import router from './router'
import store from './store'
const whiteList = ['/loginPage', '/createAccount', '/forgetpassword', '/404']
router.beforeEach((to, from, next) => {
let userInfo = store.state.user.userInfo
if (to.meta?.title) {
document.title = to.meta.title
}
if (!JSON.parse(localStorage.getItem('userInfo'))) {
if (whiteList.includes(to.path)) {
console.log(1)
// 在免登录白名单,直接进入
next()
} else {
console.log(2)
next('/loginPage') // 否则全部重定向到登录页
}
} else {
if (userInfo.id) {
if (store.state.user.jurisdiction?.length == 0) {
console.log(3)
store.dispatch('addJurisdiction', userInfo.jurisdiction).then((_) => {
next({ ...to, replace: true })
})
} else {
console.log(4)
next()
}
} else {
console.log(5)
store.commit('SET_USERINFO', JSON.parse(localStorage.getItem('userInfo')))
store.dispatch('addJurisdiction', JSON.parse(localStorage.getItem('userInfo')).jurisdiction).then((_) => {
next({ ...to, replace: true })
})
}
}
})
踩坑
layout.children = recursionRouter(Jurisdiction, layout.children)
// 本想着深拷贝一份路由表,不修改原来数据。
// 路由添加不能采用JSON.parse(JSON.strigify())序列化,路由里有function方法, 序列化的时候function会丢失