【问题标题】:How I can use vuex nested modules?如何使用 vuex 嵌套模块?
【发布时间】:2021-02-26 21:00:50
【问题描述】:

正如 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 is not found 因为我猜rollout 是一个文件夹而不是一个模块,因此site 是一个模块而不是rollout 的嵌套模块。

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。可能我脑子里有点乱,能不能帮我把这些概念说清楚?

【问题讨论】:

    标签: vue.js vuex vuex-modules


    【解决方案1】:

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

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

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

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

    【讨论】:

    • 当使用require.context 循环和store.registerModule 自动注册嵌套模块时,我使用一个空对象作为新的嵌套模块注册的目标,但它还没有现有的父级,但试图找出原因它没有正确注册。我在那个空对象中添加了namespaced: true,现在一切都按预期工作了!这应该被标记为答案!
    【解决方案2】:

    我完全被这篇文章中给出的问题和答案误导了,它可能也对许多其他人这样做了,因为它在发布这篇文章时有 1K 的浏览量。 自己摸索后,决定发在这里,以免浪费更多人的时间。

    答案:

    使用

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

    (见下文说明)

    如果您不在coreCountry、coreRegion 和rolloutSite 中输入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() 不是函数”的错误,它现在可能已经修复,但我认为“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: { ... }
    }
    

    core 和 rollout 将被识别为模块而不是文件夹。

    所以,有

    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 中的account

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

    【讨论】:

      猜你喜欢
      • 2018-11-15
      • 2019-04-13
      • 1970-01-01
      • 2018-04-06
      • 2021-06-05
      • 2022-08-24
      • 1970-01-01
      • 2019-12-23
      • 1970-01-01
      相关资源
      最近更新 更多