setup中如何使用mapState

着急的同学可以直接查看文末的最终版本以及使用说明

推演过程

vuex提供了mapState、mapMutations…辅助函数,让我们能够方便的映射vuex中的state、getters、mutations以及actions

computed: {
	...mapState(['name', 'age']),
	// otherComputed...
}

mapState函数实际生成的是一个如下的对象,我们将其展开到组件的配置中

computed: {
	name: function(){
		return this.$store.state.name
	},
	age: function(){
		return this.$store.state.age
	}
    // ...otherComputed
}

但是setup中没有computed选项,的计算属性只能使用computed组合式api进行创建,如下

import { useStore } from 'vuex'
// store等同于this.$store,setup中没有this,只能这个书写
const store = useStore()
const name = computed(() => store.state.name)
const age = computed(() => store.state.age)

因此我们只需要将mapState返回的对象改造为setup的组合式API写法即可解决这个问题

// 此处省略依赖导入...
const stateObj = mapState(['name', 'age'])
/*
// stateObj结果
{
    name: function(){
        return this.$store.state.name
    },
    age: function(){
        return this.$store.state.age
    }
}
*/
const myState = {}
for (const key in stateObj) {
    if (Object.hasOwnProperty.call(stateObj, key)) {
        // fn函数中需要使用到this.$store,因为setup中没有this,因此需要手动修改该函数的this指向
        const fn = stateObj[key].bind({ $store: useStore() })
        myState[key] = computed(fn)
    }
}
// 然后就可以正常使用我们仓库的数据了
const { name, age } = myState
console.log(name.value, age.value);

优化

每次这么写会很麻烦,不仅会使键盘的寿命缩减,还容易把手上磨出茧子,因此我们可以对这些东西进行封装

// 省略导入语法
function setupMapState (keys) {
    // 使用仓库对象
    const $store = useStore()
    // 根据参数进行映射
    const stateFn = mapState(keys)
    const res = {}
    for (const key in stateFn) {
        if (Object.hasOwnProperty.call(stateFn, key)) {
            // 修改计算函数内部this指向
            const fn = stateFn[key].bind({ $store })
            // 存储
            res[key] = computed(fn)
        }
    }
    // 将映射结果返回
    return res
}

大功告成,接下来就可以正常使用了

const { name, age } = setupMapState(['name', 'age'])
console.log(name.value, age.value);

vuex的模块化

如果vuex进行了模块化拆分,我们在进行映射时需要传递对应的模块名,显然现在的一个参数难以满足我们的需求,展开运算符可以帮上大忙

// 省略导入语法
function setupMapState (...arg) {
    // 使用仓库对象
    const $store = useStore()
    // 根据参数进行映射
    const stateFn = mapState(...arg)
    const res = {}
    for (const key in stateFn) {
        if (Object.hasOwnProperty.call(stateFn, key)) {
            // 修改计算函数内部this指向
            const fn = stateFn[key].bind({ $store })
            // 存储
            res[key] = computed(fn)
        }
    }
    // 将映射结果返回
    return res
}

这样就能支持其他模块的导入了

const { name, age } = setupMapState(['name', 'age'])
console.log(name.value, age.value);
const { name: otherModuleName } = setupMapState('otherModule' ,['name']) 
console.log(otherModuleName.value);

最终版本

其他的映射函数也可以进行处理,这样就更加方便了

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 = {}
    // 如果映射的是state或getters需要使用computed组合式API包裹,因此做了这样一个判断
    const isMapData = [mapState, mapGetters].includes(mapFn)
    for (const key in stateFn) {
        if (Object.hasOwnProperty.call(stateFn, key)) {
            // 修改映射函数内部this指向
            const fn = stateFn[key].bind({ $store })
            // 记录:state或getters使用computed进行包裹,其他的直接记录
            res[key] = isMapData ? computed(fn) : fn
        }
    }
    // 返回结果
    return res
}
// 导出对应的setup映射函数
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)
}

使用说明

封装完成之后只需要进行导入,然后和使用正常的辅助函数用法相同

// 映射state
const { name } = setupMapState(['name', 'age'])
// 其他模块的state
const { name: homeName } = setupMapState('home', ['name'])
// 映射mutations
const { setName } = setupMapMutations(['setName'])
// 映射getters
const { names } = setupMapGetters({
  names: 'getName'
})
// 映射actions
const { postName } = setupMapActions(['postName'])
// 传参方式和vuex辅助函数相同

小结

今天又掉了一撮头发,如果帮助到了你就留下个赞吧
手动比心♥

  • 14
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值