给vue-router做权限设定的时候,碰到beforeEach无限循环的问题
这是因为next方法导致的,每次next(path)都会重新执行一次beforeEach
next() 表示路由成功,直接进入to路由,不会再次调用router.beforeEach()
next('login') 表示路由拦截成功,重定向至login,会再次调用router.beforeEach()
下面是我改写后的代码:
// /src/permission.js 错误的代码
import VueRouter from 'vue-router'
import { permissions } from './mockData/permissionData'
import { routes } from '@/router/config.js'
import router from '@/router/index.js'
console.log(router)
router.beforeEach(async (to, from, next) => {
// 登录后获取权限数据 permissions
if (to.name === 'Login' || to.name === 'notFound') {
next()
} else {
// 获取符合权限的routes 可以放到store中
const accessRoutes = getAccessRoutes()
const newRouter = new VueRouter({
routes: []
})
router.matcher = newRouter.matcher
router.addRoutes(accessRoutes)
const path = to.path === '/' ? accessRoutes[0] : to
console.log('to path:', path)
// next({ ...path, replace: true })
next()
}
})
router.afterEach(() => {
// NProgress.done()
console.log('router.afterEach')
})
function getAccessRoutes () {
// [{},{ path:'/',id:'101', children: [...] }]
// 首先过滤第一层,如果第一层都没有,子级的就不用检查了
const menuArr = routes.filter(item => {
if (item.meta && item.meta.id) {
return permissions.some(data => {
return data.pmId === item.meta.id
})
} else {
return true
}
})
// 再过滤menuArr里面的children
const accessRoutes = menuArr.map(item => {
let childArr = null
if (menuArr.children) {
childArr = menuArr.children.filter(item => {
if (item.meta && item.meta.id) {
return permissions.some(data => {
return data.pmId === item.meta.id
})
} else {
return true
}
})
}
if (childArr !== null) {
item.children = childArr
}
return item
})
console.log('accessRoutes:', accessRoutes)
return accessRoutes
}
删除了permission.js,把路由限定放在了router/index.js
// /src/router/config.js
// 因为permission权限验证的时候也需要用到routes数组,所以抽出来单独形成一个文件
import Layout from '@/views/layout/index'
import Login from '@/views/Login'
export const routes = [
{
path: '/',
name: 'Login',
component: Login
},
{
path: '/home',
meta: {
id: 1000
},
component: Layout,
children: [
{
path: '/home/index',
name: 'Home',
meta: {
id: 1000
},
component: () => import(/* webpackChunkName: "home" */ '../views/Home.vue')
}
]
},
{
path: '/about',
meta: {
id: 101
},
component: Layout,
children: [
{
path: '/about/index',
name: 'About',
meta: {
id: 101
},
// route level code-splitting
// this generates a separate chunk (about.[hash].js) for this route
// which is lazy-loaded when the route is visited.
component: () => import(/* webpackChunkName: "about" */ '../views/About.vue')
},
{
path: '/about/detail',
name: 'AboutDetail',
meta: {
id: 101004
},
component: () => import(/* webpackChunkName: "aboutDetail" */ '../views/AboutDetail.vue')
}
]
},
{
path: '*',
name: 'notFound',
redirect: '/',
component: Login
}
]
// mock的权限数据
export const permissions = [
{
pmCode: 'about',
pmId: 101,
pmName: 'About',
pmType: 'MENU'
},
{
pmCode: 'about:detail',
pmId: 101004,
pmName: '查看',
pmType: 'BUTTON'
}
]