vuex中modules的使用

modules提出的目的:

“由于使用单一状态树,应用的所有状态会集中到一个比较大的对象。当应用变得非常复杂时,store 对象就有可能变得相当臃肿。”

(来自vuex文档)

模块化思想在做项目较大的时候十分有用,下面依据vuex文档简单记录一下modules的使用方式

如何使用modules

const moduleA = {
  state: { ... },//局部state
  mutations: { ... },
  actions: { ... },
  getters: { ... }
}

const moduleB = {
  state: { ... },//局部state
  mutations: { ... },
  actions: { ... }
}

const store = new Vuex.Store({
state:{ ... },//全局state modules: { a: moduleA, b: moduleB } })

 1.其中moduleA和modulesB的state为局部state,而store对象建立时与modules同级的为全局state

  访问moduleA中的state :store.state.a,  全局state :store.state

2.对于moduleA和moduleB的getters和mutations中,对于参数与全局的getters和mutations存在一定区别

  getters和mutations中第一个参数的state为局部state,

  getters的第二个参数为全局getters,第三个为根state(rootState)

3.对于moduleA和moduleB的和mutations中

局部state通过context.state,全局state通过content.rootState ,全局getters通过rootGetters

actions: {
    test({ state, rootState }) {
      ....
    }

4.moduleA和moduleB除了state为局部,其他stategetters和mutations,actions可以全局直接使用,但参数的作用域全局的存在不同

module 的命名空间

什么是命名空间,就是在module中添加一个属性,namespaced: true, 就完成了,而命的名字就是在全局中导入的module的名字,

如上边代码中moduleA对应的a为其名字。

  • 注意:module中state不受命名空间影响,本身就是局部state的
  • 而getters和mutations,actions在命名后为局部,不能直接在全局调用

代码来自vuex文档

const store = new Vuex.Store({
  modules: {
    account: {
      namespaced: true,

      // 模块内容(module assets)
      state: { ... }, // 模块内的状态已经是嵌套的了,使用 `namespaced` 属性不会对其产生影响
      getters: {
        isAdmin () { ... } // -> 调用需要添加指定命名,getters['account/isAdmin']
      },
      actions: {
        login () { ... } // -> dispatch('account/login')
      },
      mutations: {
        login () { ... } // -> commit('account/login')
      },

      // 嵌套模块
      modules: {
        // 继承父模块的命名空间
        myPage: {
          state: { ... },
          getters: {
            profile () { ... } // -> getters['account/profile']
          }
        },

        // 进一步嵌套命名空间
        posts: {
          namespaced: true,

          state: { ... },
          getters: {
            popular () { ... } // -> getters['account/posts/popular']
          }
        }
      }
    }
  }
})

 在命名空间里面你要是想访问全局的getters,mutations和actions的话,需要注意一些

getters存在四个参数,state(局部), getters(局部), rootState(全局), rootGetters(全局)

例子

getters: {
      // 在这个模块的 getter 中,`getters` 被局部化了
      // 你可以使用 getter 的第四个参数来调用 `rootGetters`
      someGetter (state, getters, rootState, rootGetters) {
        getters.someOtherGetter // -> 'foo/someOtherGetter'
        rootGetters.someOtherGetter // -> 'someOtherGetter'
      },
      someOtherGetter: state => { ... }
    },

 对于mutation,不存在rootState可以访问全局state

对于action,存在rootState和rootGetters

接下来一个问题,因为命名空间,commit和dispatch都局部化,所以如何使用全局的commit和dispatch呢

答案是:通过传入{root:true}作为第三个参数打开路径调用全局的commit和dispatch

直接上例子

actions: {
      // 在这个模块中, dispatch 和 commit 也被局部化了
      // 他们可以接受 `root` 属性以访问根 dispatch 或 commit
      someAction ({ dispatch, commit, getters, rootGetters }) {
        dispatch('someOtherAction') // -> 'foo/someOtherAction'
        dispatch('someOtherAction', null, { root: true }) // -> 'someOtherAction'

        commit('someMutation') // -> 'foo/someMutation'
        commit('someMutation', null, { root: true }) // -> 'someMutation'
      },

如果你想在module中注册一个全局的actions,可以通过如下方式,

在actions中添加一个属性(action函数名字),通过对象方式,添加root为true的属性以及在handle中添加action方法{root:true,handle(){...}}

actions: {
        someAction: {
          root: true,
          handler (namespacedContext, payload) { ... } // -> 'someAction'
        }
      }

接下来是如何将命名空间与语法糖(mapState,mapMutations,mapGetters,mapActions)结合起来

...mapState({
    a: state => state.moduleA.a,
    b: state => state.moduleB.b
  })
...mapGeters({
a:"moduleA/a"
})


...mapActions([‘moduleA/foo’]) =>使用为 this[moduleA/foo]()
...mapMutations([‘moduleA/foo’])=>使用为 this[moduleA/foo]()

 如上所见,简单直白

关于上边为什么mapState和mapGetters为什么要采用这种方式,起一个别名a,由于不起别名a,如何采用同Action和Mutation一样的写法的话

emm,那么使用为this['moduleA/a'],但是在template使用模板语法的时候表示为{{this['moduleA/a']}}得不出想要的数据,所以采用别名

获取另一种写法

...mapState(“moduleA”,["a"])
...mapGetters("moduleA",["a"] ...mapActions("moduleA",[‘foo’]) =>使用为 this.foo() ...mapMutations("moduleA",[‘foo’]) =>使用为 this.foo()

如果你觉得需要些指定命名的路径比较麻烦,你可以调用createNamespacedHelpers这个创建某个命名空间的辅助函数

import { createNamespacedHelpers } from 'vuex'

const { mapState, mapActions } = createNamespacedHelpers('moduleA')

...mapState({
    a: state => state.a,
    b: state => state.b
  })

...mapActions([‘foo’]) =>使用为 this.foo()
...mapMutations([‘foo’]) =>使用为 this.foo()

原文地址:https://www.cnblogs.com/kongbaifeiye/p/12577941.html