Vue.js首次访问MenuAdmin不加载,刷新后正常的问题求助
问题分析与解决方案
我来帮你梳理下这个问题的根源,你猜的方向是对的——首次访问时setAdminBx确实是在getAdminBx之后执行的,这就导致路由初始化时拿不到管理员标识,MenuAdmin自然加载不出来,而刷新页面时localStorage里已经存储了之前设置的值,所以getAdminBx能拿到正确结果。
具体原因拆解
- 你的
router/index.js在应用启动时就同步执行了,这时候localStorage里的PermiBxAdmin还没有被设置。 setAdminBx是在bx_users.js的getUserBx这个异步Action里调用的,而这个Action的执行时机(比如在路由守卫、App初始化钩子)是晚于路由初始化的,所以首次加载时,路由判断hasAdmin的时候,异步请求还没完成,getAdminBx只能返回null。- 刷新页面时,
localStorage里已经保留了上一次请求后设置的管理员标识,所以路由初始化时getAdminBx能拿到正确值,adminRouter被加入路由,MenuAdmin正常加载。
解决方案:动态添加路由
最稳妥的做法是不在路由初始化阶段同步判断管理员权限,而是等异步获取到管理员身份后,再动态添加对应的路由。具体步骤如下:
1. 修改路由文件(router/index.js)
把adminRouter单独抽离,初始化时只保留基础路由:
import Vue from 'vue' import Router from 'vue-router' import { getAdminBx } from '@/utils/auth' Vue.use(Router) /* Layout */ import Layout from '@/layout' export const constantRoutes = [ { path: '/redirect', component: Layout, hidden: true, children: [ { path: '/redirect/:path*', component: () => import('@/views/redirect/index') } ] }, { path: '/login', component: () => import('@/views/login/index'), hidden: true }, { path: '/auth-redirect', component: () => import('@/views/login/auth-redirect'), hidden: true }, { path: '/404', component: () => import('@/views/error-page/404'), hidden: true }, { path: '/401', component: () => import('@/views/error-page/401'), hidden: true }, { path: '/', component: Layout, redirect: '/dashboard', children: [ { path: 'dashboard', component: () => import('@/views/dashboard/index'), name: 'Dashboard', meta: { title: 'Painel', icon: 'dashboard', affix: true } } ] } ] // 单独导出admin路由,方便后续动态添加 export const adminRouter = { /* 你的管理员路由配置 */ } export const asyncRoutes = [ { path: '*', redirect: '/404', hidden: true } ] const createRouter = () => new Router({ mode: 'history', scrollBehavior: () => ({ y: 0 }), routes: constantRoutes }) const router = createRouter() export function resetRouter() { const newRouter = createRouter(); router.matcher = newRouter.matcher } export default router
2. 修改用户信息Action(store/modules/bx_users.js)
在异步获取管理员身份后,动态添加路由:
import { getTokenBx, setTokenBx, removeTokenBx, getUserInfoBx, setAdminBx } from '@/utils/auth' import { getUserCurrent, getUserAdmin } from '@/api/bx/user' import router, { adminRouter } from '@/router' // 导入路由和adminRouter const state = { bx_token: getTokenBx(), bx_name: '', bx_userinfo: '' } const mutations = { // 你的mutations代码不变 } const actions = { async getUserBx({ commit }) { const userInfo = getUserInfoBx(); const url = userInfo.DOMAIN; const token = userInfo.AUTH_ID; const id = userInfo.ID commit('SET_USERID', id); commit('SET_TOKEN', token); commit('SET_DOMAIN', url); commit('SET_EXPIRES', userInfo.AUTH_EXPIRES); commit('SET_REFRESH', userInfo.REFRESH_ID); commit('SET_MEMBER', userInfo.member_id) try { // 先获取管理员身份 const adminResponse = await getUserAdmin(url, token) const isAdmin = adminResponse.result commit('SET_USERADMIN', isAdmin) setAdminBx(isAdmin) // 如果是管理员,动态添加路由(Vue Router 3.x用addRoutes,4.x用addRoute) const hasAdminRoute = router.options.routes.some(route => route.path === adminRouter.path) if (isAdmin && !hasAdminRoute) { router.addRoutes([adminRouter]) // 如果adminRouter是Layout的子路由,需要添加到对应的父路由下: // router.addRoute('Dashboard', adminRouter) // 这里的'Dashboard'是父路由的name } // 再获取用户基础信息 const userResponse = await getUserCurrent(url, token) commit('SET_USERINFO', userResponse.result) setTokenBx(token) } catch (error) { console.error('加载用户信息失败:', error) throw error } }, // 其他Action代码不变 } export default { actions, namespaced: true, state, mutations }
3. 完善路由守卫(permission.js)
确保在用户信息加载完成后再放行路由,避免路由跳转时动态路由还没添加:
import router from './router' import store from './store' router.beforeEach(async (to, from, next) => { // 判断是否已加载用户信息 const hasUserInfo = !!store.state.bx_users.bx_userinfo if (!hasUserInfo) { try { await store.dispatch('bx_users/getUserBx') // 重新跳转,确保动态路由已生效 next({ ...to, replace: true }) } catch (error) { // 处理错误,比如跳转到登录页 next('/login') } } else { next() } })
额外注意点
- 如果你的
adminRouter是嵌套在Layout下的子路由,记得用router.addRoute(parentRouteName, adminRouter)来添加,而不是addRoutes。 - 刷新页面时,因为
localStorage里有管理员标识,路由守卫会重新触发getUserBx,再次动态添加路由,这里通过hasAdminRoute判断可以避免重复添加。
内容的提问来源于stack exchange,提问作者Brunooo
相关产品推荐
相关产品推荐

