什么是Module?
由于使用单一状态树,应用的所有状态会集中到一个比较大的对象,当应用变得非常复杂时,store 对象就有可能变得相当臃肿;
为了解决以上问题,Vuex 允许我们将 store 分割成模块(module);
每个模块拥有自己的 state、mutation、action、getter、甚至是嵌套子模块;

module的局部状态
对于模块内部的 mutation 和 getter,接收的第一个参数是模块的局部状态对象:

module的命名空间
默认情况下,模块内部的action和mutation仍然是注册在全局的命名空间中的:
这样使得多个模块能够对同一个 action 或 mutation 作出响应;
Getter 同样也默认注册在全局命名空间;
如果我们希望模块具有更高的封装度和复用性,可以添加 namespaced: true 的方式使其成为带命名空间的模块:
当模块被注册后,它的所有 getter、action 及 mutation 都会自动根据模块注册的路径调整命名;
module修改或派发根组件
如果我们希望在action中修改root中的state,那么有如下的方式:
//moudle下的home.js
const homeModule = {
namespaced: true, //命名空间
state() {
return {
homeCounter: 100
}
},
getters: {
//这里会有四个参数
doubleHomeCounter(state, getters, rootState, rootGetters) {
return state.homeCounter * 2
},
otherGetter(state) {
return 100
}
},
mutations: {
increment(state) {
state.homeCounter++
}
},
actions: {
//这里一共有六个参数
incrementAction({commit, dispatch, state, rootState, getters, rootGetters}) {
commit("increment")
//派发根组件,z修改也应用到根组件上
commit("increment", null, {root: true})
// dispatch
// dispatch("incrementAction", null, {root: true})
}
}
}
export default homeModule
//命名空间在组件中的使用
<template>
<div>
<h2>root:{{ $store.state.rootCounter }}</h2>
<h2>home:{{ $store.state.home.homeCounter }}</h2>
<h2>user:{{ $store.state.user.userCounter }}</h2>
<hr>
<h2>{{ $store.getters["home/doubleHomeCounter"] }}</h2>
<button @click="homeIncrement">home+1</button>
<button @click="homeIncrementAction">home+1</button>
</div>
</template>
<script>
export default {
methods: {
homeIncrement() {
this.$store.commit("home/increment")
},
homeIncrementAction() {
this.$store.dispatch("home/incrementAction")
}
}
}
</script>
module的辅助函数
如果辅助函数有三种使用方法:
方式一:通过完整的模块空间名称来查找;
方式二:第一个参数传入模块空间名称,后面写上要使用的属性;(也用)
方式三:通过 createNamespacedHelpers 生成一个模块的辅助函数;(用的比比较多)
<template>
<div>
<hr>
<h2>{{ homeCounter }}</h2>
<h2>{{ doubleHomeCounter }}</h2>
<!-- <h2>{{ doubleRootCounter }}</h2> -->
<button @click="increment">home+1</button>
<button @click="incrementAction">home+1</button>
<hr>
</div>
</template>
<script>
import { createNamespacedHelpers, mapState, mapGetters, mapMutations, mapActions } from "vuex";
//3.写法三需要引入
import { useState, useGetters } from '../hooks/index'
// const { mapState, mapGetters, mapMutations, mapActions } = createNamespacedHelpers("home")
export default {
computed: {
// 1.写法一:
// ...mapState({
// homeCounter: state => state.home.homeCounter
// }),
// ...mapGetters({
// doubleHomeCounter: "home/doubleHomeCounter"
// })
// 2.写法二:
// ...mapState("home", ["homeCounter"]),
// ...mapGetters("home", ["doubleHomeCounter"])
// 3.写法三:
...mapState(["homeCounter"]),
...mapGetters(["doubleHomeCounter"])
},
methods: {
// 1.写法一:
// ...mapMutations({
// increment: "home/increment"
// }),
// ...mapActions({
// incrementAction: "home/incrementAction"
// }),
// 2.写法二
// ...mapMutations("home", ["increment"]),
// ...mapActions("home", ["incrementAction"]),
// 3.写法三:
...mapMutations(["increment"]),
...mapActions(["incrementAction"]),
},
setup() {
// {homeCounter: function}
// const state = useState(["rootCounter"])
// const rootGetters = useGetters(["doubleRootCounter"])
// const getters = useGetters("home", ["doubleHomeCounter"])
const mutations = mapMutations(["increment"])
const actions = mapActions(["incrementAction"])
return {
// ...state,
// ...getters,
// ...rootGetters
// ...mutations,
// ...actions
}
}
}
</script>
<style scoped>
</style>
对useState和useGetters修改
import { mapGetters, createNamespacedHelpers } from 'vuex'
import { useMapper } from './useMapper'
export function useGetters(moduleName, mapper) {
let mapperFn = mapGetters
if (typeof moduleName === 'string' && moduleName.length > 0) {
mapperFn = createNamespacedHelpers(moduleName).mapGetters
} else {
mapper = moduleName
}
return useMapper(mapper, mapperFn)
}
import { mapState, createNamespacedHelpers } from 'vuex'
import { useMapper } from './useMapper'
export function useState(moduleName, mapper) {
let mapperFn = mapState
if (typeof moduleName === 'string' && moduleName.length > 0) {
mapperFn = createNamespacedHelpers(moduleName).mapState
} else {
mapper = moduleName
}
return useMapper(mapper, mapperFn)
}
//useMapper.js
import { computed } from 'vue'
import { useStore } from 'vuex'
export function useMapper(mapper, mapFn) {
// 拿到store独享
const store = useStore()
// 获取到对应的对象的functions: {name: function, age: function}
const storeStateFns = mapFn(mapper)
// 对数据进行转换
const storeState = {}
Object.keys(storeStateFns).forEach(fnKey => {
const fn = storeStateFns[fnKey].bind({$store: store})
storeState[fnKey] = computed(fn)
})
return storeState
}
762

被折叠的 条评论
为什么被折叠?



