说明

本质上就是对象嵌套对象

image.png

Vuex - 6、分模块modules - 图3

定义

文件规范

一般都是单个文件里面写对应的模块,然后export导出,通过顶层的index.js统一引入管理
image.png

Vuex 3 和 Vue 2

image.png

Vuex 4 和 Vue 3

子模块
image.png
index.js 统一引入
image.png

使用

使用state

store.state.模块名.变量名 进行使用
image.png

模块内的 getter、mutation、actions

子模块
image.png
使用子模块 getter,和state不一样,getters是直接合并到根的getters里面
image.png

因此,如果和vuex根下的getters、mutation 重名的话,直接使用会一起执行。

那么我们想让模块的变量、方法独立,要怎么办?看下面命名空间

=====================

命名空间 namespaced

设置

image.png
image.png

image.png

定义

  1. const modules = {
  2. foo: {
  3. namespaced: true,// 开启命名空间
  4. getters: {
  5. // 会多3个参数,带root的是vuex根里面的state和getters
  6. someGetter (state, getters, rootState, rootGetters) {
  7. getters.someOtherGetter // -> 'foo/someOtherGetter'
  8. rootGetters.someRootOtherGetter // -> 'someRootOtherGetter'
  9. },
  10. someOtherGetter: state => { ... }
  11. },
  12. mutations: {
  13. // mutations的参数没变化,第一个是state,第二个是外部传入的参数
  14. someMutations(state,payload){
  15. }
  16. },
  17. actions: {
  18. // 在这个模块中, dispatch 和 commit 也被局部化了
  19. // 他们可以接受 `root` 属性以访问根 dispatch 或 commit
  20. someAction ({ dispatch, commit, getters, rootGetters },payload) {
  21. getters.someGetter // -> 'foo/someGetter'
  22. rootGetters.someGetter // -> 'someGetter'
  23. // 如果要使用root的,使用时可以通过第三个参数{ root: true } 表示
  24. dispatch('someOtherAction') // -> 'foo/someOtherAction'
  25. dispatch('someOtherAction', null, { root: true }) // -> 'someOtherAction'
  26. // 如果要使用root的,使用时可以通过第三个参数{ root: true } 表示
  27. commit('someMutation') // -> 'foo/someMutation'
  28. commit('someMutation', null, { root: true }) // -> 'someMutation'
  29. },
  30. someOtherAction (ctx, payload) { ... }
  31. }
  32. }
  33. }

getter 和 mutation

设置命名空间后,现在mutation 和 getter的第一个参数是模块的局部状态对象,并且多了根root的相关内容,方便你想调用根的
image.png

action

image.png

外部组件中使用

getters

image.png

mutation 和 actions

image.png

=====================

批量使用模块的mapXXX

之前我们介绍的map方法都是使用根里面的,也就是vuex第一层的
image.png

如果是模块,有3种方法

1、通过完整的模块空间名称来查找

image.png

2、第一个参数传入模块空间名称,后面写上要使用的属性

image.png
image.png

3、通过 createNamespacedHelpers 生成一个模块的辅助函数(推荐)

选项API

image.png
image.png
image.png

组合API

image.png
image.png

useState 和 useGetters 是我们之前封装改造的,但是之前没考虑过模块,因此还要进行改造

hook/useMapper.js

  1. import { computed } from 'vue'
  2. import { mapState, useStore } from 'vuex'
  3. export function useMapper(mapper, mapFn) {
  4. // 拿到store独享
  5. const store = useStore()
  6. // 获取到对应的对象的functions: {name: function, age: function}
  7. const storeStateFns = mapFn(mapper)
  8. // 对数据进行转换
  9. const storeState = {}
  10. Object.keys(storeStateFns).forEach(fnKey => {
  11. const fn = storeStateFns[fnKey].bind({$store: store})
  12. storeState[fnKey] = computed(fn)
  13. })
  14. return storeState
  15. }

image.png

hook/useState.js

  1. import { mapState ,createNamespacedHelpers } from 'vuex'
  2. import { useMapper } from './useMapper'
  3. // moduleName放第二个参数好点,没有的话相当于用根
  4. export function useState(mapper,moduleName) {
  5. /*
  6. mapState = {
  7. a:function(){return this.$store.state.a},
  8. b:function(){return this.$store.state.b},
  9. }
  10. */
  11. let mapperFn = mapState
  12. if(moduleName){
  13. mapperFn = createNamespacedHelpers(moduleName).mapState
  14. }
  15. return useMapper(mapper, mapperFn)
  16. }

image.png
hook/useGetters.js

  1. import { mapGetters ,createNamespacedHelpers } from 'vuex'
  2. import { useMapper } from './useMapper'
  3. // moduleName放第二个参数好点,没有的话相当于用根
  4. export function useGetters(mapper,moduleName) {
  5. /*
  6. mapGetters = {
  7. a:function(){return this.$store.state.a},
  8. b:function(){return this.$store.state.b},
  9. }
  10. */
  11. let mapperFn = mapGetters
  12. if(moduleName){
  13. mapperFn = createNamespacedHelpers(moduleName).mapGetters
  14. }
  15. return useMapper(mapper, mapperFn)
  16. }