路由守卫中获取store状态需显式导入store实例,Vue2用import store from '@/store',Vue3推荐同样方式;异步权限校验须结合本地缓存、loading拦截和路由元信息分级控制。

在路由守卫中获取 store 状态,核心不是“能不能取”,而是“怎么取才可靠、不报错、不为空”。尤其当权限数据依赖异步请求(比如登录后拉取用户角色、菜单列表),直接读 store.state 往往拿到空对象或默认值——这不是代码写错了,是时序没对上。
Vue 2:不能用 this.$store,要 import store 实例
在 router/index.js 的全局守卫里,this 指向的是 router 实例,不是 Vue 组件,所以 this.$store 是 undefined。必须显式导入 store:
开箱即用的技能链路由引擎。13 条预定义链覆盖搜索、开发、审查、MLOps、法律、创意等场景,三层路由架构(触发词→SAD反馈→DAG编排),recall@10=96.97%。配置驱动(chains.yaml),零代码扩展。pip install skill-weave-chains 一键安装。
- 顶部加 import store from '@/store'(路径按你项目实际调整)
- 守卫内用
store.state.xxx或store.getters.xxx读取,例如:const userInfo = store.state.user.userInfo;const hasPermission = store.getters.hasRole('admin'); - 注意:如果 state 初始为空(如
userInfo: null),而权限校验又依赖它,此时应配合meta.requiresAuth+ 异步兜底逻辑,不能只靠同步读取
Vue 3(Vuex 或 Pinia):用 useStore 需在 setup 内,守卫中仍需 import
Vue 3 的 Composition API 中,useStore() 只能在组件的 setup() 或 onBeforeRouteXXX 等组合式守卫中调用。但 router.beforeEach 是普通函数,依然无法访问组件上下文:
- 方案一(推荐):继续 import { store } from '@/store'(Pinia 同理,导出的是 createPinia() 创建的实例)
- 方案二:改用 router.beforeEach(async (to, from, next) => {...}),在守卫内手动 dispatch action 触发权限初始化,并 await 完成后再判断
- 示例关键片段:
if (to.meta.requiresAuth && !store.state.user.token) {<br> await store.dispatch('user/fetchUserInfo');<br>}<br>if (store.getters.canAccess(to.name)) { next(); } else { next('/403'); }
解决“异步权限校验不生效”的三个实操要点
权限数据不是静态配置,而是登录后从接口返回的,这就带来“守卫执行时数据还没回来”的经典问题。绕开它,得靠状态+流程双管控:
- 持久化兜底:登录成功后,把 token 和基础权限存 localStorage;守卫启动时优先读本地缓存做快速判断,避免白屏等待
-
守卫内加 loading 状态拦截:定义一个
store.state.app.routeGuardReady = false,登录完成后设为 true;守卫中若未 ready,先next(false)暂停跳转,等 ready 后再router.push(to) - 路由元信息分级控制:不用所有页面都 requireAuth。把路由分三类——公开页(/login /404)、登录后可进但无需权限(/home)、需特定角色才放行(/admin/users)。守卫只对第三类做细粒度校验,降低失败概率
别踩这些坑
- 在守卫里调用
store.commit修改状态没问题,但不要在 commit 里做异步操作(应交给 action) - 不要在
beforeEach里反复调用store.dispatch('xxx'),容易触发多次重复请求,建议加 loading 标记或用 Promise 缓存 - Pinia 用户注意:Pinia 实例默认不支持在模块外直接 import 使用(除非你导出了 store 工厂函数并手动调用),确保
export const useUserStore = defineStore(...)后,在 router 中import { store } from '@/store'是一个已创建好的实例


















