我如何使用 vuex 嵌套模块?

How I can use vuex nested modules?

正如 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 是模块而不是 [= 的嵌套模块18=].

Vuex 文档show如何使用 helper 绑定嵌套模块中的内容,但不显示具有嵌套模块的商店的架构。

LIST_REQUEST 是一个动作,来自 types.js 并且定义为:

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

所以在 site.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 仍然必须将操作转换为函数

如何使用嵌套模块解决这些问题并使用 index.js。可能我脑子有点迷糊,你能帮忙理清一下这些概念吗?

如果你想嵌套模块并给它们自己的命名空间,你应该设置 namespaced 属性:

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

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

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

我完全被这个 post 中给出的问题和答案误导了,它可能也对许多其他人造成了误导,因为它在 post 发布时有 1000 次浏览。 自己想通后,我决定post放在这里,以免浪费更多人的时间。

答案:

使用

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

(见下面的解释)

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

this.LIST_REQUEST(),请在其中输入 namespaced: true
methods: {
  ...mapActions('rollout/site', [
    LIST_REQUEST
  ])
}

关于“LIST_REQUEST() is not a function”的错误可能现在已经修复了,但我认为“rollout/site/LIST_REQUEST”是一个奇怪的函数名称。也许你可以使用你拥有的来定义动作(如果它不起作用,可以通过尝试周围的语法来实现?)

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

但是,我会推荐更常见的方式 (Vuex guide also uses this) 来定义操作:

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 Reference 中定义)是一个对象

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. 直接列出导入的模块(保留导入语句中的名称): modules: { coreCountry, coreRegion }
  2. 列出导入但重命名的模块: modules: { country: coreCountry, region: coreRegion }
  3. 或者当场定义一个模块(不导入): 就像我给出的答案中的 core: { module content here }rollout: { module content here },或者 vuex guide
  4. 中的 account

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