vue3.0下如何使用mapState,mapGetters和mapActions

vue3.0下如何使用mapState,mapGetters和mapActions

      • 1、新建useMapper.js
      • 2、新建useState.js
      • 3、新建useGetters.js
      • 4、新建useActions.js
      • 5、页面中使用


vue2.0中使用mapState及mapActions的方式

 

// 使用mapState
computed: { 
	...mapState({ 
		//... 
	}) 
}

methods: {
	...mapActions(['fnA', 'fnB'])
}


vue3.0中获取state和使用actions的方式

import {computed} from 'vue'
import {useStore} from 'vuex'

setup() {
	const store = useStore();
	const stateA = computed(() => store.state.stateA);
	const stateB = computed(() => store.state.stateB);
	
	const methodA = store.dispatch('methodA', {name: '张三'});
}

那如何才能在vue3下使用mapState这些api呢?

答案是封装mapState,mapGetters,mapActions方法。

 

1、新建useMapper.js

 

import { useStore } from 'vuex'
import { computed } from 'vue'

export function useStateMapper(mapper, mapFn) {
    const store = useStore();

    const storeStateFns = mapFn(mapper);

    const storeState = {};
    Object.keys(storeStateFns).forEach(fnKey => {
        // vuex源码中mapState和mapGetters的方法中使用的是this.$store,所以更改this绑定
        const fn = storeStateFns[fnKey].bind({ $store: store });
        storeState[fnKey] = computed(fn)

    })

    return storeState
}

export function useActionMapper(mapper, mapFn) {
    const store = useStore();
    
    const storeActionsFns = mapFn(mapper);

    const storeAction = {};

    Object.keys(storeActionsFns).forEach(fnKey => {
        storeAction[fnKey] = storeActionsFns[fnKey].bind({ $store: store })
    })

    return storeAction
}

2、新建useState.js

import { mapState, createNamespacedHelpers } from 'vuex'

import { useStateMapper } from './useMapper'
import {checkType} from './index'
/**
 * 
 * @param {*} moduleName 模块名称
 * @param {*} mapper state属性集合 ['name', 'age']
 * @returns 
 */
export function useState(moduleName, mapper) {
    let mapperFn = mapState;
    
	// 如果使用模块化,则使用vuex提供的createNamespacedHelpers方法找到对应模块的mapState方法
    if (checkType(moduleName) === "[object String]" && moduleName.length > 0) {
        mapperFn = createNamespacedHelpers(moduleName).mapState
    }
    
    return useStateMapper(mapper, mapperFn)
}

3、新建useGetters.js

import { mapGetters, createNamespacedHelpers } from 'vuex'

import { useStateMapper } from './useMapper'
import {checkType} from './index'
/**
 * 
 * @param {*} moduleName 模块名称
 * @param {*} mapper getters属性集合 ['name', 'age']
 * @returns 
 */
export function useGetters(moduleName, mapper) {
    let mapperFn = mapGetters;
    
	// 如果使用模块化,则使用vuex提供的createNamespacedHelpers方法找到对应模块的mapGetters方法
    if (checkType(moduleName) === "[object String]" && moduleName.length > 0) {
        mapperFn = createNamespacedHelpers(moduleName).mapGetters
    }

    return useStateMapper(mapper, mapperFn)
}

4、新建useActions.js

import { mapActions, createNamespacedHelpers } from 'vuex';
import {useActionMapper} from './useMapper'
import {checkType} from './index'
/**
 * 
 * @param {*} moduleName 模块名称
 * @param {*} mapper 方法名集合 ['fn1', 'fn2']
 * @returns 
 */
export function useActions(moduleName, mapper) {
    let mapperFn = mapActions;
    
	// 如果使用模块化,则使用vuex提供的createNamespacedHelpers方法找到对应模块的mapActions方法
    if (checkType(moduleName) === "[object String]" && moduleName.length > 0) {
        mapperFn = createNamespacedHelpers(moduleName).mapActions
    }

    return useActionMapper(mapper, mapperFn)
}

5、页面中使用

 

<template>
    <div class="home">
        <span>姓名:{{name}} 年龄:{{age}} 性别:{{sex}}</span>
        <button @click="changeName">改名</button>
    </div>
</template>

<script>
// @ is an alias to /src
import {useState} from '@/utils/useState'
import {useActions} from '@/utils/useAction'
export default {
    name: "home",
    setup() {
        const storeState = useState('home', ['name', 'age', 'sex'])
        const storeActions = useActions('home', ['setName'])
        const changeName = () => {
            storeAction.setName('李四')
        }
        return {
            changeName,
            ...storeState,
            ...storeActions
        };
    },
};
</script>

posted @ 2022-05-17 22:44  小羊不挑食  阅读(1880)  评论(1编辑  收藏  举报