如何使用 vuex 嵌套模块?



正如 Vuex 文档所说,当项目开始增长时,我们需要一种方法来将状态管理分离到一个更加独立和模块化的可扩展解决方案中。在这里,命名空间提供了帮助。可悲的是,在编写 Vuex 模块部分时,缺乏如何有效使用它们的信息和示例。

这是我的商店结构

store
|- modules
|- core
|- country.js
|- region.js
|- ...
|- roullout
|- site.js
|- index.js

此处模块寄存器index.js

import Vuex from 'vuex'
// Core modules
import coreCountry from "@/store/modules/core/country";
import coreRegion from "@/store/modules/core/region";
// Rollout modules
import rolloutSite from "@/store/modules/rollout/site";
export default new Vuex.Store({
modules: {
// Core modules
core: {
country: coreCountry,
region: coreRegion,
},
// Rollout modules
rollout: {
site: rolloutSite
}
}
})

现在在某些组件中,我尝试定义操作

methods: {
...mapActions('rollout/site', [
LIST_REQUEST
])
}

这里第一个错误:找不到rollout/site,因为我想rollout是一个文件夹而不是一个模块,因此site是一个模块而不是rollout的嵌套模块。

Vuex 文档展示了如何使用 helper 在嵌套模块中绑定内容,但没有显示具有嵌套模块的存储的架构。

LIST_REQUEST是一个操作,来自类型.js定义为:

export const LIST_REQUEST = "rollout/site/LIST_REQUEST";

所以在现场.js模块我可以使用为:

const actions = {
[types.LIST_REQUEST]: async ({ commit }, payload= {}) => {
// your actions here...
},
}

由于我使用的是mapActions(),而不是像this.$store.dispatch()这样的调度操作,我可以直接做this.LIST_REQUEST()

import {
LIST_REQUEST
} from "@/store/types/rollout/site";
export default {
name: "SiteList",
created() {
this.LIST_REQUEST()
},
methods: {
...mapActions('rollout/site', [
LIST_REQUEST
])
}
}

这里有另一个错误:LIST_REQUEST() 不是一个函数。出现此错误是因为mapAction仍然必须将操作转换为函数

我如何使用嵌套模块解决这些问题并使用索引.js。也许我心里有点困惑,你能帮忙澄清这些概念吗?

我完全被这篇文章中给出的问题和答案误导了,它可能对许多其他人也是如此,因为它在发布本文时有 1K 的浏览量。 在我自己弄清楚之后,我决定把它贴在这里,这样它就不会浪费更多的人的时间。

答:

modules: {
core: {
namespaced: true,
modules {
// Core modules
country: coreCountry,
region: coreRegion,
}
},
rollout: {
namespaced: true,
modules: {
// Rollout modules
site: rolloutSite
}
}
}

(见下面的解释)

如果你不把namespaced: true放在你的coreCountrycoreRegionrolloutSite,它仍然会像this.$store.dispatch(rollout/LIST_REQUEST)一样。如果您想要this.$store.dispatch(rollout/site/LIST_REQUEST),请放入namespaced: true,或者像您说的那样,this.LIST_REQUEST()不使用

methods: {
...mapActions('rollout/site', [
LIST_REQUEST
])
}

对于"LIST_REQUEST()不是函数"的错误,也许现在已经修复了,但我认为"rollout/site/LIST_REQUEST"是一个奇怪的函数名称。也许您可以使用您拥有的东西来定义动作(如果它不起作用,也许可以通过围绕它的语法来玩转?

const actions = {
[types.LIST_REQUEST]: async ({ commit }, payload= {}) => {
// your actions here...
},
}

但是,我建议使用更常见的方式(Vuex 指南也使用它)来定义操作:

actions: {
actionName (context, payload) {
// async functions and commits here
}
}

actions: {
actionName ({ state, rootState, commit, dispatch, getters, rootGetters }, payload) {
// async functions and commits here
}
}

解释:

modules: { }中的任何内容都被视为一个模块,根据定义(在 Vuex API 参考中定义)它是一个对象

key: {
// required (can be empty)
state,
// optional (as denoted by '?')
namespaced?,
mutations?,
actions?,
getters?,
modules? // **nested modules go here**
}

因此,模块中没有文件夹的概念。当你投入

module {
core: { ... },
rollout: { ... }
}

corerollout将被识别为模块而不是文件夹。

所以,有

module {
rollout: {
site: { ... }
}
}

任何进入rollout(被识别为模块)的东西都应该是state:namespaced:mutations:actions:getters:modules:。没有别的。

因此,要在modules: { }中放入模块,您可以

  1. 直接列出导入的模块(保留 import 语句中的名称):modules: { coreCountry, coreRegion }
  2. 列出导入的模块,但已重命名:modules: { country: coreCountry, region: coreRegion }
  3. 或当场定义模块(不导入): 就像我给出的答案中的core: { module content here }rollout: { module content here },或者 Vuex 指南中的account

基本上,要制作嵌套模块,您只需将子模块放入父模块的modules: { }内(可以像答案一样当场定义,也可以在其他地方制作并导入),例如根存储本身modules: { }中的corerollout

如果要嵌套模块并为其提供自己的命名空间,则应设置namespaced属性:

export default new Vuex.Store({
modules: {
rollout: {
namespaced: true,
site: rolloutSite
}
}
})

使用mapActions帮助程序时,除了帮助程序本身之外,您不必导入任何其他内容。假设rollout/site有一个名为foo的方法,您应该可以这样做:

methods: {
...mapActions({ foo: 'rollout/site/foo' })
}

最新更新