vuex提供了mapState、mapMutations…辅助函数,让我们能够方便的映射vuex中的state、getters、mutations以及actions
1 2 3 4
| computed: { ...mapState(['name', 'age']), }
|
mapState函数实际生成的是一个如下的对象,我们将其展开到组件的配置中
1 2 3 4 5 6 7 8 9
| computed: { name: function(){ return this.$store.state.name }, age: function(){ return this.$store.state.age } }
|
但是setup中没有computed选项,的计算属性只能使用computed组合式api进行创建,如下
1 2 3 4 5
| import { useStore } from 'vuex'
const store = useStore() const name = computed(() => store.state.name) const age = computed(() => store.state.age)
|
因此我们只需要将mapState返回的对象改造为setup的组合式API写法即可解决这个问题
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| const stateObj = mapState(['name', 'age'])
const myState = {} for (const key in stateObj) { if (Object.hasOwnProperty.call(stateObj, key)) { const fn = stateObj[key].bind({ $store: useStore() }) myState[key] = computed(fn) } }
const { name, age } = myState console.log(name.value, age.value);
|
优化
每次这么写会很麻烦,不仅会使键盘的寿命缩减,还容易把手上磨出茧子,因此我们可以对这些东西进行封装
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| function setupMapState (keys) { const $store = useStore() const stateFn = mapState(keys) const res = {} for (const key in stateFn) { if (Object.hasOwnProperty.call(stateFn, key)) { const fn = stateFn[key].bind({ $store }) res[key] = computed(fn) } } return res }
|
大功告成,接下来就可以正常使用了
1 2
| const { name, age } = setupMapState(['name', 'age']) console.log(name.value, age.value);
|
vuex的模块化
如果vuex进行了模块化拆分,我们在进行映射时需要传递对应的模块名,显然现在的一个参数难以满足我们的需求,展开运算符可以帮上大忙
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| function setupMapState (...arg) { const $store = useStore() const stateFn = mapState(...arg) const res = {} for (const key in stateFn) { if (Object.hasOwnProperty.call(stateFn, key)) { const fn = stateFn[key].bind({ $store }) res[key] = computed(fn) } } return res }
|
这样就能支持其他模块的导入了
1 2 3 4
| const { name, age } = setupMapState(['name', 'age']) console.log(name.value, age.value); const { name: otherModuleName } = setupMapState('otherModule' ,['name']) console.log(otherModuleName.value);
|
最终版本
其他的映射函数也可以进行处理,这样就更加方便了
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
| import { computed } from 'vue'
import { mapActions, mapGetters, mapMutations, mapState, useStore } from 'vuex' function mapAll (keys, mapFn) { const $store = useStore() const stateFn = mapFn(...keys) const res = {} const isMapData = [mapState, mapGetters].includes(mapFn) for (const key in stateFn) { if (Object.hasOwnProperty.call(stateFn, key)) { const fn = stateFn[key].bind({ $store }) res[key] = isMapData ? computed(fn) : fn } } return res }
export function setupMapState (...keys) { return mapAll(keys, mapState) } export function setupMapMutations (...keys) { return mapAll(keys, mapMutations) } export function setupMapGetters (...keys) { return mapAll(keys, mapGetters) } export function setupMapActions (...keys) { return mapAll(keys, mapActions) }
|
使用说明: 封装完成之后只需要进行导入,然后和使用正常的辅助函数用法相同
1 2 3 4 5 6 7 8 9 10 11 12 13
| const { name } = setupMapState(['name', 'age'])
const { name: homeName } = setupMapState('home', ['name'])
const { setName } = setupMapMutations(['setName'])
const { names } = setupMapGetters({ names: 'getName' })
const { postName } = setupMapActions(['postName'])
|