这主要是由于路由守卫(
router.beforeEach
)中的逻辑以及权限验证机制的实现方式。下面原因分析
路由守卫中的权限验证:
在router.beforeEach
中,你有一个逻辑来检查每个路由的meta.auth
属性。如果meta.auth
为false
(即用户没有权限访问该路由),则重定向到404页面。这个逻辑是在路由跳转之前执行的,因此如果用户尝试直接访问一个他们没有权限的路由(通过手输URL),他们将被重定向到404页面。动态更新权限:
你的代码通过监听store.watch
来动态更新allRouters
数组,并基于这个数组来更新路由的meta.auth
属性。然而,这种更新是响应式的,意味着它依赖于外部状态(如从服务器获取的菜单数据)的变化。如果用户直接访问一个URL,而这个URL对应的路由在菜单数据加载完成之前没有被赋予正确的meta.auth
值,那么他们可能会被错误地重定向到404页面。首次加载问题:
在应用首次加载时,allRouters
数组可能是空的,因此所有路由的meta.auth
都可能被设置为false
。这意味着在菜单数据加载并更新allRouters
之前,用户无法通过直接输入URL访问任何页面。
routes: [
{
path: '/redirect/:path*',
component: () => import('./views/redirect/index')
component: () => import('./views/redirect/index'),
meta: {}
},
{
path: '/',
redirect: '/index'
redirect: '/index',
meta: {}
},
{
path: '/index',
}
},
{
path: '/home/center',
name: 'controlCenter',
component: () => import('./views/home/center/Index.vue'),
meta: { title: 'mobile.route.controlCenter', authority:'/home/center'},
},
const router = new Router({
routes
});
// 接口请求回来的所有页面数组
const allRouters = [];
// 匹配所有页面的数组
function findAllRouters(arr) {
function findRouter(nodes) {
nodes.forEach(node => {
if (node.resourceType === 2 && !node.subResources) {
allRouters.push(node);
}
if (node.subResources && node.subResources.length) {
findRouter(node.subResources);
}
});
}
findRouter(arr);
}
// 更新静态路由里的meta权限标识
function updateRouterMeta() {
router.options.routes[0].children.forEach(e => {
e.meta.auth = !allRouters.length ? false : !!allRouters.find(f => f.frontUrl === e.path);
});
}
// 添加路由守卫
router.beforeEach((to, from, next) => {
// 监听异步请求,有了菜单数据后
store.watch((state, getters) => getters.authority, (authority) => {
if (authority.length) {
if (!allRouters.length) {
findAllRouters(authority);
}
// 更新权限标识
updateRouterMeta();
// 更新完权限标识后,根据权限表示跳转
if (to.meta.auth) {
next();
} else {
next('/404');
}
// 无菜单数据跳转到404, 同时也要刷新权限标识
} else {
updateRouterMeta();
next('/404');
}
});
if (to.path === '/404' || to.path === '/' || to.path === '/index') {
next();
} else {
// 如果有meta auth属性,则根据auth属性跳转,无的话,详情页未在权限平台配置的,直接放行
if ('auth' in to.meta) {
if (to.meta.auth) {
next();
} else {
next('/404');
}
// 首次刷新的情况
} else {
next();
}
]
}
});
export default router;