Vue3+Vite+Vuex 页面重载时subscribe无法监听mutation问题
问题根因
核心是监听器注册时机晚于重载场景下的mutation执行时机:
- 你当前main.js的执行逻辑是:先触发
store.dispatch('auth/attempt', localStorage.getItem('token')),这个action执行过程中会同步/异步触发SET_TOKEN、SET_USER等mutation。 - 等上述dispatch的Promise状态变为完成后,你才执行
app.use(store)完成store注入、挂载应用,而你的store.subscribe监听器一般写在组件逻辑、路由守卫或依赖应用挂载的插件中,此时才会完成注册。 - 等监听器注册完成时,页面重载阶段触发的所有mutation早就执行完毕,自然无法被监听到。
登录场景下应用早已完成挂载、监听器提前注册完成,所以触发mutation时可以被正常捕获。
另外你的代码存在Vue3兼容问题:ADD_USER_DATA mutation中使用的Vue.set是Vue2专属API,Vue3中直接赋值即可实现响应式,保留该写法会抛出运行时异常。
修复方案
二选一即可,推荐优先用方案2,逻辑更稳妥:
- 方案1:调整main.js执行顺序,先完成应用挂载、监听器注册,再执行初始化的用户身份校验逻辑
调整后核心代码参考:// 先完成全局配置、插件、全局组件注册 app.config.globalProperties.emitter = mitt(); app.component('font-awesome-icon', FontAwesomeIcon) app.use(router) .use(store) .use(VueToast) .use(i18n) // 挂载应用,触发组件内部的监听器注册逻辑 app.mount('#app') // 所有监听器就位后,再执行初始化token校验 store.dispatch('auth/attempt', localStorage.getItem('token')) - 方案2:将subscribe监听器注册逻辑提前到store实例创建完成后立即执行,不依赖应用挂载流程
在store的入口定义文件中,创建完store实例就直接注册监听:// store/index.js import { createStore } from 'vuex' const store = createStore({ // 原有store配置:modules、state、mutations等 }) // store创建完成立刻注册监听,全局生效 store.subscribe((mutation, state) => { // 自定义mutation监听逻辑 }) export default store
额外兼容修复:修改ADD_USER_DATA mutation的Vue2旧写法,适配Vue3响应式逻辑:
ADD_USER_DATA: (state, data) => { Object.keys(data).forEach( key => { state.user[key] = data[key] }) }
内容的提问来源于stack exchange,提问作者Bryan van der Starre
相关产品推荐
相关产品推荐

