“[vuex] 状态字段 foo 被 foobar 上的同名模块覆盖”,在玩笑中使用 deepmerge 辅助函数

Ins*_*ane 8 vue.js jestjs vuex vuejs2 vue-test-utils

我正在使用辅助函数在我的笑话中创建一个商店。helper 函数使用 deepmerge 将基本配置与自定义配置合并。这会导致多个控制台警告

[vuex] state field "cart" was overridden by a module with the same name at "cart"
[vuex] state field "customer" was overridden by a module with the same name at "customer"
[vuex] state field "checkout" was overridden by a module with the same name at "checkout"
Run Code Online (Sandbox Code Playgroud)

store.js(为了演示目的减少到最低限度)

import cart from './modules/cart'
import checkout from './modules/checkout'
import customer from './modules/customer'

Vue.use(Vuex)

export const config = {
    modules: {
        cart,
        customer,
        checkout,
    },
}

export default new Vuex.Store(config)
Run Code Online (Sandbox Code Playgroud)

测试utils.js

import merge from 'deepmerge'
import { config as storeConfig } from './vuex/store'

// merge basic config with custom config
export const createStore = config => {
    const combinedConfig = (config)
        ? merge(storeConfig, config)
        : storeConfig
    return new Vuex.Store(combinedConfig)
}
Run Code Online (Sandbox Code Playgroud)

利用里面的辅助函数

somejest.test.js

import { createStore } from 'test-utils'

const wrapper = mount(ShippingComponent, {
    store: createStore({
        modules: {
            checkout: {
                state: {
                    availableShippingMethods: {
                        flatrate: {
                            carrier_title: 'Flat Rate',
                        },
                    },
                },
            },
        },
    }),
    localVue,
})
Run Code Online (Sandbox Code Playgroud)

如何解决控制台警告?

ski*_*tle 5

我认为这个警告在这种情况下有些误导。这在技术上是正确的,只是没有帮助。

以下代码将生成相同的警告。它不使用deepmerge,vue-test-utils或者jest但我相信根本原因与原来的问题相同:

const config = {
  state: {},

  modules: {
    customer: {}
  }
}

const store1 = new Vuex.Store(config)
const store2 = new Vuex.Store(config)
Run Code Online (Sandbox Code Playgroud)
<script src="https://unpkg.com/vue@2.6.11/dist/vue.js"></script>
<script src="https://unpkg.com/vuex@3.4.0/dist/vuex.js"></script>
Run Code Online (Sandbox Code Playgroud)

此示例中有两个关键部分需要触发警告:

  1. 多家商店。
  2. state配置中的根对象。

问题中的代码肯定有多个商店。一个是在 的末尾创建的store.js,另一个是由 创建的createStore

该问题没有显示根state对象,但确实提到代码已减少。我假设完整的代码确实有这个对象。

那么为什么这会触发该警告呢?

模块state存储在根state对象内。尽管我的示例中的模块没有明确包含任何模块,但state它仍然存在。这state将存储在state.customer. 因此,当创建第一个商店时,它会customer向该根state对象添加一个属性。

到目前为止还没有问题。

但是,当创建第二个商店时,它使用相同的根state对象。在此阶段制作副本或合并配置不会有帮助,因为复制的配置state也将具有该customer属性。第二个商店也尝试添加到customerroot state。然而,它发现该属性已经存在,感到困惑并记录警告。

官方文档对此有一些介绍:

https://vuex.vuejs.org/guide/modules.html#module-reuse

解决此问题的最简单方法是使用根函数state

state: () => ({ /* all the state you currently have */ }),
Run Code Online (Sandbox Code Playgroud)

每个商店都会调用该函数并获取自己的状态副本。data这与使用组件的函数相同。

如果您实际上不需要root,state您也可以通过完全删除它来修复它。如果没有state指定,那么 Vuex 将state每次创建一个新的根对象。