4.Vuex核心概念
4.5 Modules
Vuex实例允许划分为多个模块。
每个模块包含自己的state
、mutations
、actions
、getters
、嵌套modules
。
// store/index.js
import Vue from 'vue'
import Vuex from 'vuex'
import moduleA from './modules/moduleA'
import moduleB from './modules/moduleB'
Vue.use(Vuex)
export default new Vuex.Store({
modules: {
a: moduleA,
b: moduleB,
},
state: {
count: 0,
},
})
// store/modules/moduleA.js
export default {
state: {
count: 10,
},
mutations: {
},
getters: {
},
actions: {
},
}
// store/modules/moduleB.js
export default {
state: {
count: 20,
},
mutations: {
},
getters: {
},
actions: {
},
}
<template>
<div>
模块A的count:{{this.$store.state.a.count}}
<br/>
模块B的count:{{this.$store.state.b.count}}
</div>
</template>
<script>
export default {
name: "ModulesDemo"
}
</script>
尝试提交模块的mutation
。
// store/index.js
import Vue from 'vue'
import Vuex from 'vuex'
import moduleA from './modules/moduleA'
import moduleB from './modules/moduleB'
Vue.use(Vuex)
export default new Vuex.Store({
modules: {
a: moduleA,
b: moduleB,
},
state: {
count: 0,
},
mutations: {
increment(state) {
state.count++
},
},
})
// store/modules/moduleA.js
export default {
state: {
count: 10,
},
mutations: {
increment(state) {
state.count++
}
},
}
<template>
<div>
模块A的count:{{this.$store.state.a.count}}
<br/>
模块B的count:{{this.$store.state.b.count}}
<br/>
Vuex实例的count:{{this.$store.state.count}}
<br/>
<button @click="increment">加一</button>
</div>
</template>
<script>
export default {
name: "ModulesDemo",
methods: {
increment() {
this.$store.commit('increment')
}
},
}
</script>
注意到这里在组件中提交mutation
,Vuex实例及其modules
中的mutation
都会被触发。
添加命名空间。
// store/modules/moduleA.js
export default {
namespaced: true,
state: {
count: 10,
},
mutations: {
increment(state) {
state.count++
}
},
}
<template>
<div>
模块A的count:{{this.$store.state.a.count}}
<br/>
模块B的count:{{this.$store.state.b.count}}
<br/>
Vuex实例的count:{{this.$store.state.count}}
<br/>
<button @click="increment">加一</button>
</div>
</template>
<script>
export default {
name: "ModulesDemo",
methods: {
increment() {
this.$store.commit('a/increment')
}
},
}
</script>
通过添加{root: true}
在全局命名空间中调度Action
或提交mutation
。
// store/modules/moduleB.js
export default {
namespaced: true,
state: {
count: 20,
},
mutations: {
increment(state) {
state.count++
}
},
actions: {
someAction({commit}) {
commit('increment') // 触发模块B的increment
// commit('increment', null, {root: true}) // 触发Vuex实例全局的increment
},
},
}
<template>
<div>
模块A的count:{{this.$store.state.a.count}}
<br/>
模块B的count:{{this.$store.state.b.count}}
<br/>
Vuex实例的count:{{this.$store.state.count}}
<br/>
<button @click="increment">加一</button>
</div>
</template>
<script>
export default {
name: "ModulesDemo",
methods: {
increment() {
this.$store.dispatch('b/someAction')
}
},
}
</script>
使用mapState
、mapGetters
和mapActions
。
// store/index.js
import Vue from 'vue'
import Vuex from 'vuex'
import moduleA from './modules/moduleA'
import moduleB from './modules/moduleB'
Vue.use(Vuex)
export default new Vuex.Store({
modules: {
a: moduleA,
b: moduleB,
},
state: {
count: 1,
},
mutations: {
increment(state) {
state.count++
},
})
// store/modules/moduleA.js
export default {
namespaced: true,
state: {
count: 10,
},
mutations: {
increment(state) {
state.count++
}
},
getters: {
sumWithRootCount (state, getters, rootState) {
return state.count + rootState.count
},
},
actions: {
incrementIfOddOnRootSum ({ state, commit, rootState }) {
if ((state.count + rootState.count) % 2 === 1) {
commit('increment')
// commit('increment', null, {root: true})
}
}
},
}
// store/modules/moduleB.js
export default {
namespaced: true,
state: {
count: 20,
},
mutations: {
increment(state) {
state.count++
}
},
actions: {
someAction2: {
root: true,
handler({commit}) {
// commit('increment')
commit('increment', null, {root: true})
}
},
},
}
<template>
<div>
模块A的count:{{a}}
<br/>
模块B的count:{{b}}
<br/>
Vuex实例的count:{{this.$store.state.count}}
<br/>
模块A的count+Vuex实例的count={{sumWithRootCount}}
<br/>
<button @click="incrementIfOddOnRootSum">加一</button>
</div>
</template>
<script>
import {
mapState,
mapGetters,
mapActions,
} from 'vuex'
export default {
name: "ModulesDemo",
computed: {
...mapState({
a: state => state.a.count,
b: state => state.b.count,
}),
...mapGetters({
sumWithRootCount: 'a/sumWithRootCount'
})
},
methods: {
...mapActions({
incrementIfOddOnRootSum: 'a/incrementIfOddOnRootSum'
}),
}
}
</script>
参考: