核心是路由守卫需等待用户信息加载完成后再决策跳转,所有分支必须且仅调用一次return next(),配合loading状态避免白屏,并对请求失败、超时做兜底处理。

核心是不让跳转动作发生在用户信息加载完成之前,必须等异步结果明确后,再由守卫决定放行、重定向或挂起。
守卫里不能直接 await 后调 next() 两次
常见错误是异步获取用户后,条件判断跳转,但末尾又无条件调一次 next(),导致覆盖前一次决策:
- ✅ 正确写法:所有分支都只调一次 next(),且必须有返回值
- ❌ 错误写法:
if (user) { next() } else { next('/login') }; next()—— 最后一个 next() 会执行,破坏权限逻辑 - 推荐统一用 return next(xxx) 显式终止函数执行,避免遗漏
用 loading 状态阻断渲染,避免白屏
用户信息未返回时,页面不该空白等待,也不该贸然渲染受保护内容。需配合 UI 层做状态隔离:
- 全局守卫中不直接控制 UI,但可设置一个应用级状态(如 authStatus = 'checking')
- 受保护的 Layout 或根组件监听该状态:为 null 时显示骨架屏或 loading 动画;为 false 时跳登录;为 true 时才渲染子路由
- Vue 3 可用 ref 管理;React 可用 useState + useEffect 触发检查
请求失败和超时必须兜底
网络不可靠,权限接口慢或失败时,守卫不能卡住或静默退出:
- 给 axios 请求加 timeout: 5000,捕获 ERR_NETWORK 或 ETIMEDOUT
- try/catch 中统一处理:跳转到 /error 页面,或弹提示“正在重试”,并自动重试 1 次
- 切忌只 console.error 却不调 next() —— 路由会挂起,页面卡死
进阶:多个依赖串行校验更稳妥
仅查用户信息不够?还需角色、功能开关等,建议组合判断,而非嵌套回调:
- Vue Router 全局守卫支持 async/await:
router.beforeEach(async (to, from, next) => { ... }) - 用 Promise.all 并行拉取(适合独立接口),或 await 串行(适合有依赖顺序的场景)
- 示例:
const user = await getUser(); if (!user) return next('/login'); const perm = await checkRole(user.id); if (!perm) return next('/403');










