我的编程空间,编程开发者的网络收藏夹
学习永远不晚

vue3.0使用mapState,mapGetters和mapActions的方式

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

vue3.0使用mapState,mapGetters和mapActions的方式

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'

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'

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'

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 /class="lazy" data-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>

vue3对vuex中mapState,mapGetters辅助函数封装

1. readonly API的使用

在我们传递给其他组件数据时,如果直接将响应式数据传递给子组件。子组件如果使用数据不规范,修改了父组件传进来的props值没有任何反馈。

// 父组件
// <ReadonlyChild :info="info" />
setup() {
    const info = reactive({
      name: "哇哈哈",
    });
    return {
      info,
    };
}
// 子组件
setup(props) {
    const onChangeInfo = () => {
      const info = props.info;
      // 修改父组件传来的props 没有任何反馈。
      info.name = "woowow";
    };
    return {
      onChangeInfo,
    };
}

开发中我们往往希望其他组件使用我们传递的内容,但是不允许它们修改时,就可以使用 readonly了。

// 父组件
// <ReadonlyChild :info="infoReadonly" />
setup() {
    const info = reactive({
      name: "哇哈哈",
    });
    const infoReadonly = readonly(info);
    const onChangeInfo = () => {
      // 在父组件中可修改info中的值,子组件依然可响应更新
      info.name = "父组件给你的值";
    };
    return {
      infoReadonly,
      onChangeInfo
    };
}
// 子组件
setup(props) {
    const onChangeInfo = () => {
      const info = props.info;
      // 此时修改props时,控制台会有一个警告:
      // Set operation on key "name" failed: target is readonly. 
      info.name = "woowow";
    };
    return {
      onChangeInfo,
    };
}

2. 响应式变量直接解构会失去响应性

将响应式变量直接解构会失去其响应性

const info = reactive({ age: 18 });
// 直接解构后 age 值失去响应性,当 onChangeAge 函数触发时,age值不在变,而ageRef 依然具有响应性
const { age } = info;
const { age: ageRef } = toRefs(info);
const onChangeAge = () => {
  info.age++;
};

3. watchEffect 清除副作用

watchEffect API 可自动收集依赖项,当依赖项改变时触发侦听器函数。当我们在侦听器函数执行额外的副作用函数,例如:发送网络请求时。每当依赖性项变更都会发起一个新的网络请求,那么上一次的网络请求应该被取消掉。这个时候我们就可以清除上一次的副作用了。

setup() {
    const count = ref(0);
    const onChangeCount = () => {
      count.value++;
    };
    watchEffect((onInvalidate) => {
      // 侦听器函数中需要发起网络请求,用setTimeout模拟
      const timer = setTimeout(() => {
        console.log("请求成功啦");
      }, 2000);
      // 在侦听器函数重新执行时触发onInvalidate函数
      onInvalidate(() => {
        // 在这个函数中清除请求
        clearTimeout(timer);
        console.log("onInvalidate 回调触发");
      });
      // 自动收集count的依赖
      console.log("count-在改变", count.value);
    });
    return {
      count,
      onChangeCount,
    };
  }

4. setup 函数访问Vuex中Store数据

4.1 使用mapState辅助函数

通常需要通computed函数来获取state中数据,并保存响应性。

setup() {
    const store = useStore();
    // 在setup中要获取store中的state。如果state非常多,无疑这样做很繁琐
    const uName = computed(() => store.state.name);
    const uAge = computed(() => store.state.age);
    const uHeight = computed(() => store.state.height);
    
    const storeState = mapState(["name", "age", "height"]);
    // 需要对返回值进行处理
    const resStoreState = {};
    Object.keys(storeState).forEach((fnKey) => {
      const fn = storeState[fnKey].bind({ $store: store });
      resStoreState[fnKey] = computed(fn);
    });
    return {
      uName,
      uAge,
      uHeight,
      ...resStoreState,
    };
  }

封装成hooks如下:

// useState.js
import { computed } from "vue";
import { useStore, mapState } from "vuex";
export default function useState(mapper) {
  const store = useStore();
  const storeStateFns = mapState(mapper);
  const storeState = {};
  Object.keys(storeStateFns).forEach((fnKey) => {
    const fn = storeStateFns[fnKey].bind({ $store: store });
    storeState[fnKey] = computed(fn);
  });
  return storeState;
}

在组件中使用时

import useState from "@/hooks/useState";
setup() {
    // 数组用法
    const state = useState(["name", "age", "height"]);
    // 对象用法,可使用别名
    const stateObj = useState({
      uName: (state) => state.name,
      uAge: (state) => state.age,
      uHeight: (state) => state.height,
    });
    return {
      ...state,
      ...stateObj,
    };
  }

4.2 mapGetters 辅助函数的封装

其原理与mapState 函数封装类似

// useGetters.js
import { computed } from "vue";
import { mapGetters, useStore } from "vuex";
export default function useGetters(mapper: any) {
  const store = useStore();
  const storeGettersFns = mapGetters(mapper);
  const storeGetters = {};
  Object.keys(storeGettersFns).forEach((fnKey) => {
    const fn = storeGettersFns[fnKey].bind({ $store: store });
    storeGetters[fnKey] = computed(fn);
  });
  return storeGetters;
}

useState和useGetters两个函数相似度很高,在进一下封装

// useMapper.js
import { computed } from "vue";
import { useStore } from "vuex";
export default function useMapper(mapper, mapFn) {
  const store = useStore();
  const storeStateFns = mapFn(mapper);
  const storeState = {};
  Object.keys(storeStateFns).forEach((fnKey) => {
    const fn = storeStateFns[fnKey].bind({ $store: store });
    storeState[fnKey] = computed(fn);
  });
  return storeState;
}
// useState.js
import { mapState } from "vuex";
import useMapper from "./useMapper";
export default function useState(mapper) {
  return useMapper(mapper, mapState);
}
// useGetters.js
import { mapGetters } from "vuex";
import useMapper from "./useMapper";
export default function useGetters(mapper: any) {
  return useMapper(mapper, mapGetters);
}

4.3 对module的支持

useState 和 useGetters 函数暂时还不支持传入命名空间,进一步封装。 useMapper的封装保持不变。

// useState.js
import { createNamespacedHelpers, mapState } from "vuex";
import useMapper from "./useMapper";
export default function useState(mapper, moduleName) {
  let mapperFn = mapState;
  if (typeof moduleName === "string" && moduleName.length > 0) {
    mapperFn = createNamespacedHelpers(moduleName).mapState;
  }
  return useMapper(mapper, mapperFn);
}
// useGetters.js
import { createNamespacedHelpers, mapGetters } from "vuex";
import useMapper from "./useMapper";
export default function useGetters(mapper, moduleName) {
  let mapperFn = mapGetters;
  if (typeof moduleName === "string" && moduleName.length > 0) {
    mapperFn = createNamespacedHelpers(moduleName).mapGetters;
  }
  return useMapper(mapper, mapperFn);
}
// 在组件中的使用
// Home.vue
setup() {
  const state = useState(["homeCounter"], "home");
  const stateGetter = useGetters(["doubleHomeCounter"], "home");
  return {
    ...state,
    ...stateGetter,
  }
}

以上为个人经验,希望能给大家一个参考,也希望大家多多支持编程网。

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

vue3.0使用mapState,mapGetters和mapActions的方式

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

VUE中的mapState和mapActions如何使用

本文小编为大家详细介绍“VUE中的mapState和mapActions如何使用”,内容详细,步骤清晰,细节处理妥当,希望这篇“VUE中的mapState和mapActions如何使用”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一
2023-07-02

关于Object.entries()方法的使用和实现方式

这篇文章主要介绍了关于Object.entries()方法的使用和实现方式,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
2023-02-10

MyBatis中有关int和Integer的使用方式

这篇文章主要介绍了MyBatis中有关int和Integer的使用方式,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
2023-05-13

HanLP在eclipse中的安装和使用方式

本篇内容介绍了“HanLP在eclipse中的安装和使用方式”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!HanLP由3部分组成:类库han
2023-06-02

Flex中定义和使用渲染器的方式

这篇文章主要讲解了“Flex中定义和使用渲染器的方式”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“Flex中定义和使用渲染器的方式”吧!Flex中使用渲染器(ItemRenderer)Fle
2023-06-17

单点登录的方式和JWT使用的方法是什么

这篇文章主要介绍“单点登录的方式和JWT使用的方法是什么”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“单点登录的方式和JWT使用的方法是什么”文章能帮助大家解决问题。单点登录三种方式单点登录的三种实
2023-07-05

Linux/Ubuntu下chmod命令的使用格式和方法

这篇文章主要讲解了“Linux/Ubuntu下chmod命令的使用格式和方法”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“Linux/Ubuntu下chmod命令的使用格式和方法”吧!Lin
2023-06-13

vue3中keep-alive和vue-router的结合使用方式

这篇文章主要介绍了vue3中keep-alive和vue-router的结合使用方式, 具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
2022-11-13

Linux中apt-get和apt-cache命令的使用方式

本篇内容主要讲解“Linux中apt-get和apt-cache命令的使用方式”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“Linux中apt-get和apt-cache命令的使用方式”吧!ap
2023-06-13

windows系统的安全模式使用方法和11项使用技巧

对于计算机小白来说,或者对电编程客栈脑系统没有www.cppcns.com深入了解的人都不清楚Windows系统的安全模式是干什么用的、怎么退出安全模式等操作,下面小编详细介绍各种情况下的Windows系统安全模式使用方法和技巧。1、基础知
2023-06-08

编程热搜

目录