如何在多个Vuex store间复用公共state属性与mutations?
实现方案
Vuex 原生没有内置mixins配置项,但可以完全基于原生能力合规实现需求,不需要依赖第三方插件,也不会生成独立的store模块节点。
核心思路
Vuex的store/模块配置本质就是普通JS对象,你只需要在导出store配置前,把抽离出来的公共state、mutations等属性按规则合并到业务store的配置对象里即可,最终传入Vuex的是和手写结构完全一致的标准配置,不存在兼容问题。
具体实现
1. 编写通用合并工具函数
这个函数会处理state(兼容对象/函数两种写法)、mutations、getters、actions的合并,默认业务配置的优先级高于公共mixin,同名属性会被业务逻辑覆盖:
// utils/store-merge.js export function mergeStoreMixins(baseStore, ...mixins) { // 初始化合并后的state,兼容state为函数的场景 const baseStateIsFunc = typeof baseStore.state === 'function' const mergedState = baseStateIsFunc ? baseStore.state() : { ...(baseStore.state || {}) } mixins.forEach(mixin => { // 合并mixin的state const mixinState = typeof mixin.state === 'function' ? mixin.state() : (mixin.state || {}) Object.assign(mergedState, mixinState) // 合并mutations、getters、actions,业务配置优先级更高 baseStore.mutations = { ...(mixin.mutations || {}), ...(baseStore.mutations || {}) } baseStore.getters = { ...(mixin.getters || {}), ...(baseStore.getters || {}) } baseStore.actions = { ...(mixin.actions || {}), ...(baseStore.actions || {}) } }) // 把合并后的state挂回原配置 baseStore.state = baseStateIsFunc ? () => mergedState : mergedState return baseStore }
2. 业务store中使用
你之前抽离的load-mixin.js不需要做任何修改,只需要在业务store中调用合并函数即可:
// store/store1.js import loadState from './load-mixin' import { mergeStoreMixins } from '@/utils/store-merge' // 业务store原生配置 const storeConfig = { namespaced: true, state: { // 业务自身状态 dataList: [] }, mutations: { // 业务自身变更方法 setDataList(state, list) { state.dataList = list } } } // 合并公共片段后导出,效果和直接把loading逻辑写在配置里完全一致 export default mergeStoreMixins(storeConfig, loadState)
方案优势
- 完全符合Vuex原生配置规范,没有黑魔法,所有合并逻辑可控可调试
- 不会生成独立的模块命名空间,公共状态
isLoading直接挂载在当前store的state下,调用setIsLoading也不需要加额外前缀,和你预期的mixin效果完全一致 - 冲突处理逻辑清晰:业务侧定义的同名state、mutation会覆盖公共mixin的实现,不会出现意外覆盖问题
- 兼容性强,不管是Vuex 3(Vue2配套)还是Vuex 4(Vue3配套)都可以正常使用,也不会和Vuex持久化、日志等插件产生冲突
注意:不要尝试用嵌套Vuex模块实现这个需求,模块会生成独立的state节点,访问时需要写模块路径,调用mutation也需要带命名空间前缀,无法实现直接合并的效果。
内容的提问来源于stack exchange,提问作者Eleandro Duzentos
相关产品推荐
相关产品推荐

