由于使用单一状态树,应用的所有状态会集中到一个比较大的对象。当应用变得非常复杂时,store 对象就有可能变得相当臃肿。
为了解决以上问题,Vuex 允许我们将 store 分割成模块(module)。每个模块拥有自己的 state、mutation、action、getter、甚至是嵌套子模块——从上至下进行同样方式的分割:
const moduleA = {
state: () => ({ ... }),
mutations: { ... },
actions: { ... },
getters: { ... }
}
const moduleB = {
state: () => ({ ... }),
mutations: { ... },
actions: { ... }
}
const store = new Vuex.Store({
modules: {
a: moduleA,
b: moduleB
}
})
store.state.a // -> moduleA 的状态
store.state.b // -> moduleB 的状态
这是官方的介绍,我们这里把moduleA和moduleB分开文件来说明:
首先在app.vue
同级创建 store
文件夹,里面的结果如图:
a.js
和b.js
里面的代码为:
//a.js
const state = {
money:10
}
const mutations = {
add(state,num){
state.money+=parseInt(num)
},
reduce(state,num){
state.money-=parseInt(num)
}
}
const actions={
add:({commit},num)=>{
commit('add',num)
},
reduce:({commit},num)=>{
commit('reduce',num)
}
}
export default {
namespaced:true,
state,
mutations,
actions
}
//b.js
const state = {
count:2
}
const mutations = {
add(state,num){
state.count+=num
},
reduce(state){
state.count--
}
}
const actions={
add:({commit},num)=>{
commit('add',num)
},
reduce:({commit})=>{
commit('reduce')
}
}
export default {
namespaced:true,
state,
mutations,
actions
}
这里分别定义一个价格和数量的state属性,用来改变数据。
index.js
里面代码为:
import Vue from 'vue'
import Vuex from 'vuex'
import money from './modules/a'
import count from './modules/b'
Vue.use(Vuex)
export default new Vuex.Store({
modules: {
money,
count
}
})
这里主要的就是导出的时候,是将money
和count
以module
模块的形式导出,然后在main.js
里面注册store
import Vue from 'vue'
import App from './App.vue'
import store from './store/index'
Vue.config.productionTip = false
new Vue({
render: h => h(App),
store
}).$mount('#app')
这样就可以使用a.js
和b.js
里面的state
了。表示方式为:
$store.state.money.money //a.js里面state
$store.state.count.count//b.js里面的state
这样的话,就把a.js
和b.js
的state
都绑定到store.state
上面。不管哪个界面都可以去使用任意的state
。
这里还需要说明的是a.js
和b.js
里面的mutation
的使用。先在components
里面创建a.vue
、b.vue
界面。界面中分发a.js
和b.js
的action写法如下:
<script>
import { mapActions } from "vuex";
export default {
methods: mapActions("count", ["add", "reduce"])
//没有声明module的时候用法
// methods: mapActions( ["add", "reduce"])
};
</script>
值得注意的是,这里mapActions
后面不是直接跟a.js
和b.js
的action
,而是第一个参数声明module
模块count
,后面跟着count
里面的actions
。
如何使用分发的actions
?其实是和之前是一样的
<button @click="add(num)">单价增加</button>
<button @click="reduce(num)">单价减少</button>
这里就实现了不管是a.vue
还是b.vue
都可以使用a.js
和b.js
的actions
和state
如果a.vue
里面想要使用a.js
和b.js
的actions
,则写法需要改变下,如:
<script>
import { mapActions } from "vuex";
export default {
methods: {
...mapActions("money", ["add1", "reduce1"])
...mapActions("count", ["add", "reduce"])
}
};
</script>
这样使用的话,多个module
的方法命名是不能重复的,不然会实现最后一个module里面的方法。
用法:
<button @click="add1(num)">单价增加</button>
<button @click="reduce1(num)">单价减少</button>
<br>
<button @click="add(num)">数量增加</button>
<button @click="reduce(num)">数量减少</button>