当使用 Vue Router 动态加载路由时,可能会遇到一个循环加载的问题,具体表现为 beforeach 全部被拦截,因此会出现死循环。这个问题的根本原因是路由对象在创建并注册路由前会被复制,因此在路由注册前执行一个 beforeEach 全局钩子,将会陷入死循环。为了解决这个问题,我们可以采用以下方案:
步骤
步骤一
在路由配置文件中为动态路由添加一个命名字段,使其有一个唯一标识符,如下所示:
const routes = [
{
path: '/home',
name: 'home',
component: () => import('@/views/home/index.vue'),
},
{
path: '/login',
name: 'login',
component: () => import('@/views/login/index.vue'),
},
{
path: '/about-us',
name: 'about-us',
component: () => import('@/views/about-us/index.vue'),
},
{
path: '/article-detail/:id',
name: 'article-detail',
component: () => import('@/views/article-detail/index.vue'),
meta: {
title: 'Article Detail',
author: 'admin',
},
},
{
path: '/user/:id',
name: 'user',
component: () => import('@/views/user/index.vue'),
meta: {
title: 'User',
author: 'admin',
},
},
{
path: '/404',
name: '404',
component: () => import('@/views/404.vue'),
hidden: true,
},
{
path: '*',
redirect: '/404',
hidden: true,
},
{
path: '/admin',
component: () => import('@/views/admin/index.vue'),
meta: {
title: 'Admin Dashboard',
author: 'admin',
},
children: [
{
path: 'home',
name: 'admin-home',
component: () => import('@/views/admin/home.vue'),
meta: {
title: 'Admin Home',
author: 'admin',
roles: ['admin'],
},
},
{
path: 'users',
name: 'admin-users',
component: () => import('@/views/admin/users.vue'),
meta: {
title: 'Admin Users',
author: 'admin',
roles: ['admin'],
},
},
{
path: 'articles',
name: 'admin-articles',
component: () => import('@/views/admin/articles.vue'),
meta: {
title: 'Admin Articles',
author: 'admin',
roles: ['admin'],
},
}
]
},
];
export default routes;
步骤二
在 router.beforeEach() 全局拦截器中,给每条动态路由添加一个标识符,然后再进行跳转,如下所示:
router.beforeEach((to, from, next) => {
const whiteList = ['/login', '/404']; // 不重定向白名单
if (whiteList.indexOf(to.path) !== -1) {
next();
} else {
if (!store.getters.token) { // 没有token
next('/login');
} else {
if (store.getters.roles.length === 0) { // 没有角色,需要动态加载角色
store.dispatch('getUserRoles').then(res => { // 获取用户信息
const roles = res.data.roles;
store.commit('SET_ROLES', roles); // 存储用户角色
const guestRoutes = router.options.routes; // 所有路由
const routes = buildRoutesByRoles(guestRoutes, roles); // 根据角色筛选路由
router.options.routes = routes; // 添加动态路由
router.addRoutes(routes); // 动态添加路由
next({ ...to, replace: true });
}).catch(err => {
store.dispatch('logout').then(() => {
Message.error(err || 'Verification failed, please login again');
next('/login');
});
});
} else {
if (hasPermission(store.getters.roles, to)) { // 校验权限
next();
} else {
next('/404');
}
}
}
}
});
在这个例子中,我们首先获取到了所有路由,然后根据用户角色筛选出需要添加的那些路由,将这些路由添加到 Vue Router 中,最后再进行路由跳转,这样就能够避免路由被重复添加,从而解决了 beforeach 中的死循环问题。
示例
为了更好地说明这个解决方案的作用,我将提供两个例子,分别展示该方案在对不同场景下的解决作用。
示例一:多角色权限控制
当我们生成一套后台管理系统时,可能会遇到需要对用户进行角色管理,并且需要在页面中针对不同的角色展示出不同的内容。这就需要我们在路由配置文件中进行角色控制,根据当前用户的角色来动态加载对应角色的路由。这时候,我们就会存在 beforeach 中的死循环问题,需要使用以上解决方案进行处理。
示例二:菜单栏展开总是重复展示子菜单
有时候,我们用 Vue Router 实现菜单栏的功能时,可能会出现子菜单在切换时总是重复展开的问题。这是因为每次切换路由时,路由对象都会被复制一遍,从而导致路由钩子函数被多次调用,而 vue-router 会在每次调用路由钩子函数时重新实例化路由对象,从而导致菜单重复展示。这时候,我们可以使用以上方案解决死循环问题,从而解决菜单栏展开问题。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:解决router.beforeEach()动态加载路由出现死循环问题 - Python技术站