权限路由就是根据登录的账号角色的不同返回可操作的页面不同。当前角色可操作的权限是前后端配合协同的。
1.首先搭建一张默认的无权限路由,这里我只写了一个登录页
import Vue from 'vue'
import VueRouter from 'vue-router'
Vue.use(VueRouter)
const routes = [
{
path: '',
redirect: '/login'
},
{
path: '/login',
name: 'login',
component: Login
}
]
export default router
2.创建 dynamicRoutes.js 文件。这里写动态添加的权限路由表
let dynamicRoutes = [
{
path: '/father',
component: () => {
return import('@/views/Father')
},
name: 'father',
meta: {
name: '父亲'
},
children: [
{
path: 'son',
component: () => {
return import('@/views/Father/Son')
},
name: 'son',
meta: {
name: '儿子'
}
}
]
}
]
export default dynamicRoutes
3.考虑以后可能多个组件会使用到权限路由数据,我们把权限路由的数据和生成权限路由的方法放到store中,在下面我只给出action.js里面的方法
import router from '@/router'
import dynamicRoutes from '@/router/dynamicRoutes.js'
// 筛选出有权限路由
function filterRouter (userRouter = [], allRouter = []) {
/**
* @param {Array} userRouter 后台返回的用户权限json
* @param {Array} allRouter 前端配置好的所有动态路由的集合
* @return {Array} realRoutes 过滤后的路由
*/
let realRoutes = []
allRouter.forEach(v => {
userRouter.forEach(item => {
if (item.name === v.name) {
// 创建新的对象
let obj = {
path: v.path,
component: v.component,
name: v.name,
meta: {
name: v.meta.name
}
}
// 如果后台返回的有子路由递归当前方法加入当前子路由
if (item.children && item.children.length > 0) {
obj.children = filterRouter(item.children, v.children)
}
realRoutes.push(obj)
}
})
})
return realRoutes
}
export default {
// 获取后台的路由权限
getAsyncRoutes ({ commit }) {
/**
* @param {Array} res 后台返回的用户权限json
*/
setTimeout(() => {
let res = [
{
name: 'father',
children: [
{
name: 'son'
}
]
},
{
name: 'test'
}
]
// 筛选出有权限路由
let menu = filterRouter(res, dynamicRoutes)
// 将404页面加到最后
menu = menu.concat([
{
path: '/404',
name: '404',
meta: {
name: '404'
},
component: () => {
return import('@/views/NotFound')
}
},
{
path: '**',
redirect: '/404'
}
])
// 存入session
if (!window.sessionStorage.getItem('menu')) {
window.sessionStorage.setItem('menu', JSON.stringify(menu))
}
router.$addRoutes(menu) // $addRoutes方法是重新封装的见下方
commit(ADDROUTER, menu)
}, 1000)
}
}
4.防止刷新路由消失和切换角色路由清空重新添加,我们要改造一下router.js里面的内容,以下是最终的router.js
import Vue from 'vue'
import VueRouter from 'vue-router'
import Login from '@/views/Login'
import store from '@/store'
Vue.use(VueRouter)
const routes = [
{
path: '',
redirect: '/login'
},
{
path: '/login',
name: 'login',
component: Login
}
]
const router = new VueRouter({
mode: 'history',
routes: routes
})
/**
* 为了防止重复添加路由
* 重新定义$addRoutes,调用这个方法来添加路由,这个方法会先重置路由
* 这个路由只会包括非权限页,比如登录页,再调用router.addRoutes添加权限路由
*/
router.$addRoutes = (params) => {
// 替换现有router的routes
router.matcher = new VueRouter({ // 重置路由规则
mode: 'history',
routes
}).matcher
router.addRoutes(params) // 添加路由
}
router.onReady(() => {
// 刷新页面,判断如果登录过并且有权限列表,那么动态加入权限路由
if (window.sessionStorage.getItem('menu')) {
store.dispatch('getAsyncRoutes')
}
})
export default router