如何在Nuxt.js的store中访问router?出现./router模块找不到错误
报错与设计规范双重问题
- 路径报错的直接原因:
store/index.js中写的相对导入./router,指向的是store目录下的router模块,但Nuxt项目的router相关资源默认在项目根目录的router文件夹下,store目录下根本不存在这个文件,自然触发模块找不到的报错。 - 就算把导入路径改成
../router解决了路径报错,这种手动导入路由实例的写法也不适用Nuxt场景:一来容易触发循环依赖,二来SSR渲染流程中,手动导入的独立路由实例和框架自动注入到应用全局的路由实例不是同一个,会导致客户端水合(hydration)不匹配、路由状态错乱、跳转失效的问题。 - 从Vuex设计规范来说,mutations必须是纯函数,不能包含带副作用的逻辑,路由跳转属于典型的副作用操作,本来就不应该写在mutations里。
Nuxt 中 store 访问 router 的正确方式
Nuxt 会自动把全局注入的路由实例挂载到store实例上,完全不需要手动导入模块,常用实现方法有两种:
- 方式一:拆分状态修改逻辑和副作用逻辑,将路由跳转移到 Action 中实现
保留 mutations 只负责修改响应式状态,把路由跳转这类带副作用的逻辑放到 Action 中,直接通过store实例挂载的全局属性调用$router:
页面组件里触发逻辑时直接调用action即可:// store/index.js export const state = () => ({ authenticated: false, }) // 纯函数mutations,仅修改状态,无副作用 export const mutations = { toggleAuthState(state, loginStatus) { state.authenticated = loginStatus } } // 带副作用的逻辑放到action中 export const actions = { toggleLogin({ commit }, { loginStatus, targetPath }) { commit('toggleAuthState', loginStatus) // 直接调用store实例上挂载的全局router this.$router.push(loginStatus ? targetPath : '/login') } }this.$store.dispatch('toggleLogin', { loginStatus: true, targetPath: '/profile' }) - 方式二:保留现有代码结构,通过调用上下文传递 router 实例
如果不想拆分现有代码结构,可以在组件调用store方法时,把当前组件上下文可访问的$router作为参数传入,不需要手动在store文件里导入任何模块:
组件触发时的调用示例:// store/index.js 调整后的mutations export const mutations = { toggleLogin(state, { loginStatus, path, router }) { state.authenticated = loginStatus if (loginStatus) { router.push(path) } else { router.push('/login') } } }this.$store.commit('toggleLogin', { loginStatus: false, router: this.$router })
注意事项
- 不要手动导入项目根目录的router模块:Nuxt的路由实例是框架在启动流程中自动初始化、统一注入到应用上下文的,手动导入的独立路由实例和框架使用的实例不是同一个,极易引发 hydration 不匹配、路由状态错乱的问题
- 写路由跳转路径时建议加上开头的
/,避免相对路径跳转出现层级错误 - 不要把副作用逻辑写在mutations中:违反Vuex单向数据流的设计规范,会让状态追踪、时间旅行调试功能完全失效
内容的提问来源于stack exchange,提问作者Noto Ayako
相关产品推荐
相关产品推荐

