modules提出的目的:
“由于使用单一状态树,应用的所有状态会集中到一个比较大的对象。当应用变得非常复杂时,store 对象就有可能变得相当臃肿。”
模块化思想在做项目较大的时候十分有用,下面依据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()

