说明
定义
文件规范
一般都是单个文件里面写对应的模块,然后export导出,通过顶层的index.js统一引入管理
Vuex 3 和 Vue 2
Vuex 4 和 Vue 3
子模块
index.js 统一引入
使用
使用state
模块内的 getter、mutation、actions
子模块
使用子模块 getter,和state不一样,getters是直接合并到根的getters里面
因此,如果和vuex根下的getters、mutation 重名的话,直接使用会一起执行。
那么我们想让模块的变量、方法独立,要怎么办?看下面命名空间
=====================
命名空间 namespaced
设置
定义
const modules = {
foo: {
namespaced: true,// 开启命名空间
getters: {
// 会多3个参数,带root的是vuex根里面的state和getters
someGetter (state, getters, rootState, rootGetters) {
getters.someOtherGetter // -> 'foo/someOtherGetter'
rootGetters.someRootOtherGetter // -> 'someRootOtherGetter'
},
someOtherGetter: state => { ... }
},
mutations: {
// mutations的参数没变化,第一个是state,第二个是外部传入的参数
someMutations(state,payload){
}
},
actions: {
// 在这个模块中, dispatch 和 commit 也被局部化了
// 他们可以接受 `root` 属性以访问根 dispatch 或 commit
someAction ({ dispatch, commit, getters, rootGetters },payload) {
getters.someGetter // -> 'foo/someGetter'
rootGetters.someGetter // -> 'someGetter'
// 如果要使用root的,使用时可以通过第三个参数{ root: true } 表示
dispatch('someOtherAction') // -> 'foo/someOtherAction'
dispatch('someOtherAction', null, { root: true }) // -> 'someOtherAction'
// 如果要使用root的,使用时可以通过第三个参数{ root: true } 表示
commit('someMutation') // -> 'foo/someMutation'
commit('someMutation', null, { root: true }) // -> 'someMutation'
},
someOtherAction (ctx, payload) { ... }
}
}
}
getter 和 mutation
设置命名空间后,现在mutation 和 getter的第一个参数是模块的局部状态对象,并且多了根root的相关内容,方便你想调用根的
action
外部组件中使用
getters
mutation 和 actions
=====================
批量使用模块的mapXXX
之前我们介绍的map方法都是使用根里面的,也就是vuex第一层的
如果是模块,有3种方法
1、通过完整的模块空间名称来查找
2、第一个参数传入模块空间名称,后面写上要使用的属性
3、通过 createNamespacedHelpers 生成一个模块的辅助函数(推荐)
选项API
组合API
useState 和 useGetters 是我们之前封装改造的,但是之前没考虑过模块,因此还要进行改造
hook/useMapper.js
import { computed } from 'vue'
import { mapState, 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
}
hook/useState.js
import { mapState ,createNamespacedHelpers } from 'vuex'
import { useMapper } from './useMapper'
// moduleName放第二个参数好点,没有的话相当于用根
export function useState(mapper,moduleName) {
/*
mapState = {
a:function(){return this.$store.state.a},
b:function(){return this.$store.state.b},
}
*/
let mapperFn = mapState
if(moduleName){
mapperFn = createNamespacedHelpers(moduleName).mapState
}
return useMapper(mapper, mapperFn)
}
hook/useGetters.js
import { mapGetters ,createNamespacedHelpers } from 'vuex'
import { useMapper } from './useMapper'
// moduleName放第二个参数好点,没有的话相当于用根
export function useGetters(mapper,moduleName) {
/*
mapGetters = {
a:function(){return this.$store.state.a},
b:function(){return this.$store.state.b},
}
*/
let mapperFn = mapGetters
if(moduleName){
mapperFn = createNamespacedHelpers(moduleName).mapGetters
}
return useMapper(mapper, mapperFn)
}