Vue项目中App.vue先于router.beforeEach导航守卫加载的异常问题咨询
问题:App.vue在路由导航守卫前加载导致异常
我遇到个棘手问题,得贴不少代码说明配置情况。发现我的App.vue文件居然在路由的导航守卫之前就加载了,这引发了一堆奇怪的问题。想问问:导航守卫应该覆盖整个Vue应用,还是只作用于路由?这种加载顺序是正常的吗?
注意:router.beforeEach()里的日志是在App.vue加载完成后才打印的,这明显不符合预期...
我的main.ts文件:
import App from '@/views/App.vue' import store from "./store" import createRouter from './router' const router = createRouter(store) const UI = createApp(App) UI.use(store) UI.use(router) UI.mount('#app')
我的route.ts文件:
const routes = [ { path: "/", name: "Home", component: Home, meta: { auth: true } }, ]; export default function (store: any) { const router = createRouter({ routes, history: createWebHistory(), scrollBehavior(to, from, savedPosition) { return { top: 0 } } }) router.beforeEach(async (to, from, next) => { console.log('beforeEach') store.commit(`auth/setUseAuth`, to.meta.auth) if (to.query.state != null && to.query.state !== "") { ...redacted } else { ...redacted } // 如果路由需要鉴权 if (to.meta.auth) { // 如果已有存储的token,继续 if (hasToken()) { next() return } // 如果没有存储的token if ( // 但有非空的query code... (to.query.code && to.query.code !== "") || // 或者传入了非空的JWT... (to.query.jwt && to.query.jwt !== "")) { store.dispatch({ type: 'auth/validateCode', payload: { ...redacted payload } }); next() return } } // 其他所有请求,继续执行 next() }) return router }
原因与解决方案
这种情况不正常,正常来说router.beforeEach应该在首次路由跳转(也就是加载对应组件前)触发,而App.vue作为根组件,它的生命周期钩子会在应用挂载时执行,但如果路由守卫没在组件渲染前触发,大概率是挂载顺序的问题。
核心问题:应用挂载时机不对
你当前的代码是先创建根实例,再挂载,但Vue Router需要在挂载前完成初始化,确保路由守卫能拦截首次跳转。
修复步骤:
- 调整
main.ts的顺序,确保router被use后,等待路由准备就绪再挂载应用:
import App from '@/views/App.vue' import store from "./store" import createRouter from './router' const router = createRouter(store) const UI = createApp(App) UI.use(store) UI.use(router) // 关键:等待路由准备完成后再挂载 router.isReady().then(() => { UI.mount('#app') })
Vue 3中,router.isReady()会等待路由初始化完成,包括首次导航的守卫执行完毕,这样就能保证beforeEach在App.vue的组件渲染前触发。
- 检查导航守卫中的异步逻辑
你的beforeEach是async函数,但里面的store.dispatch('auth/validateCode')是异步操作,你直接调用了next(),这会导致导航继续,而没有等待异步操作完成。如果需要等待验证完成再跳转,应该改成:
// 替换原来的dispatch部分 await store.dispatch({ type: 'auth/validateCode', payload: { ...redacted payload } }); next()
否则会出现路由跳转了,但鉴权还没完成的情况,进一步引发异常。
关于导航守卫的作用范围
导航守卫只作用于路由跳转过程,它不会直接控制根组件App.vue的加载,但可以通过拦截路由,间接阻止页面内容渲染。根组件本身会在应用挂载时渲染,所以如果根组件里有依赖路由状态的逻辑,必须确保路由守卫先执行完毕,这就是为什么要等router.isReady()再挂载。
内容的提问来源于stack exchange,提问作者Sam Britt
相关产品推荐
相关产品推荐

