欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

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

 更新時(shí)間:2022年06月24日 15:16:14   作者:一個(gè)寫前端的  
這篇文章主要介紹了vue3.0使用mapState,mapGetters和mapActions的方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教

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方法找到對(duì)應(yīng)模塊的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方法找到對(duì)應(yīng)模塊的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方法找到對(duì)應(yīng)模塊的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>

vue3對(duì)vuex中mapState,mapGetters輔助函數(shù)封裝

1. readonly API的使用

在我們傳遞給其他組件數(shù)據(jù)時(shí),如果直接將響應(yīng)式數(shù)據(jù)傳遞給子組件。子組件如果使用數(shù)據(jù)不規(guī)范,修改了父組件傳進(jìn)來的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,
? ? };
}

開發(fā)中我們往往希望其他組件使用我們傳遞的內(nèi)容,但是不允許它們修改時(shí),就可以使用 readonly了。

// 父組件
// <ReadonlyChild :info="infoReadonly" />
setup() {
? ? const info = reactive({
? ? ? name: "哇哈哈",
? ? });
? ? const infoReadonly = readonly(info);
? ? const onChangeInfo = () => {
? ? ? // 在父組件中可修改info中的值,子組件依然可響應(yīng)更新
? ? ? info.name = "父組件給你的值";
? ? };
? ? return {
? ? ? infoReadonly,
? ? ? onChangeInfo
? ? };
}
// 子組件
setup(props) {
? ? const onChangeInfo = () => {
? ? ? const info = props.info;
? ? ? // 此時(shí)修改props時(shí),控制臺(tái)會(huì)有一個(gè)警告:
? ? ? // Set operation on key "name" failed: target is readonly.?
? ? ? info.name = "woowow";
? ? };
? ? return {
? ? ? onChangeInfo,
? ? };
}

2. 響應(yīng)式變量直接解構(gòu)會(huì)失去響應(yīng)性

將響應(yīng)式變量直接解構(gòu)會(huì)失去其響應(yīng)性

const info = reactive({ age: 18 });
// 直接解構(gòu)后 age 值失去響應(yīng)性,當(dāng) onChangeAge 函數(shù)觸發(fā)時(shí),age值不在變,而ageRef 依然具有響應(yīng)性
const { age } = info;
const { age: ageRef } = toRefs(info);
const onChangeAge = () => {
? info.age++;
};

3. watchEffect 清除副作用

watchEffect API 可自動(dòng)收集依賴項(xiàng),當(dāng)依賴項(xiàng)改變時(shí)觸發(fā)偵聽器函數(shù)。當(dāng)我們?cè)趥陕犉骱瘮?shù)執(zhí)行額外的副作用函數(shù),例如:發(fā)送網(wǎng)絡(luò)請(qǐng)求時(shí)。每當(dāng)依賴性項(xiàng)變更都會(huì)發(fā)起一個(gè)新的網(wǎng)絡(luò)請(qǐng)求,那么上一次的網(wǎng)絡(luò)請(qǐng)求應(yīng)該被取消掉。這個(gè)時(shí)候我們就可以清除上一次的副作用了。

setup() {
? ? const count = ref(0);
? ? const onChangeCount = () => {
? ? ? count.value++;
? ? };
? ? watchEffect((onInvalidate) => {
? ? ? // 偵聽器函數(shù)中需要發(fā)起網(wǎng)絡(luò)請(qǐng)求,用setTimeout模擬
? ? ? const timer = setTimeout(() => {
? ? ? ? console.log("請(qǐng)求成功啦");
? ? ? }, 2000);
? ? ? // 在偵聽器函數(shù)重新執(zhí)行時(shí)觸發(fā)onInvalidate函數(shù)
? ? ? onInvalidate(() => {
? ? ? ? // 在這個(gè)函數(shù)中清除請(qǐng)求
? ? ? ? clearTimeout(timer);
? ? ? ? console.log("onInvalidate 回調(diào)觸發(fā)");
? ? ? });
? ? ? // 自動(dòng)收集count的依賴
? ? ? console.log("count-在改變", count.value);
? ? });
? ? return {
? ? ? count,
? ? ? onChangeCount,
? ? };
? }

4. setup 函數(shù)訪問Vuex中Store數(shù)據(jù)

4.1 使用mapState輔助函數(shù)

通常需要通computed函數(shù)來獲取state中數(shù)據(jù),并保存響應(yīng)性。

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);
? ? /**
? ? ?* 直接使用mapState輔助函數(shù)得不到想要的結(jié)果
? ? ?* 這樣獲取的storeState 是一個(gè) { name: ?function mappedState (){...}, age: function mappedState (){...}, height: function mappedState (){...} } 這樣的對(duì)象
? ? ?*/
? ? const storeState = mapState(["name", "age", "height"]);
? ? // 需要對(duì)返回值進(jìn)行處理
? ? 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;
}

在組件中使用時(shí)

import useState from "@/hooks/useState";
setup() {
? ? // 數(shù)組用法
? ? const state = useState(["name", "age", "height"]);
? ? // 對(duì)象用法,可使用別名
? ? const stateObj = useState({
? ? ? uName: (state) => state.name,
? ? ? uAge: (state) => state.age,
? ? ? uHeight: (state) => state.height,
? ? });
? ? return {
? ? ? ...state,
? ? ? ...stateObj,
? ? };
? }

4.2 mapGetters 輔助函數(shù)的封裝

其原理與mapState 函數(shù)封裝類似

// 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兩個(gè)函數(shù)相似度很高,在進(jìn)一下封裝

// 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 對(duì)module的支持

useState 和 useGetters 函數(shù)暫時(shí)還不支持傳入命名空間,進(jìn)一步封裝。 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,
? }
}

以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • vue+vue-fullpage實(shí)現(xiàn)整屏滾動(dòng)頁面的示例代碼(直播平臺(tái)源碼)

    vue+vue-fullpage實(shí)現(xiàn)整屏滾動(dòng)頁面的示例代碼(直播平臺(tái)源碼)

    這篇文章主要介紹了vue+vue-fullpage實(shí)現(xiàn)整屏滾動(dòng)頁面,本文通過示例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2022-06-06
  • Vue單頁面應(yīng)用保證F5強(qiáng)刷不清空數(shù)據(jù)的解決方案

    Vue單頁面應(yīng)用保證F5強(qiáng)刷不清空數(shù)據(jù)的解決方案

    最近小編遇到這樣的問題當(dāng)vue單頁面按F5強(qiáng)刷,數(shù)據(jù)就恢復(fù)初始了,這怎么辦呢?下面小編給大家?guī)砹薞ue單頁面應(yīng)用保證F5強(qiáng)刷不清空數(shù)據(jù)的解決方案,感興趣的朋友一起看看吧
    2018-01-01
  • 在Vue 中獲取下拉框的文本及選項(xiàng)值操作

    在Vue 中獲取下拉框的文本及選項(xiàng)值操作

    這篇文章主要介紹了在Vue 中獲取下拉框的文本及選項(xiàng)值操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧
    2020-08-08
  • vscode中prettier和eslint換行縮進(jìn)沖突的問題

    vscode中prettier和eslint換行縮進(jìn)沖突的問題

    這篇文章主要介紹了vscode中prettier和eslint換行縮進(jìn)沖突的問題及解決,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-10-10
  • Vue2.0 UI框架ElementUI使用方法詳解

    Vue2.0 UI框架ElementUI使用方法詳解

    這篇文章主要為大家詳細(xì)介紹了Vue2.0 UI框架ElementUI的使用方法,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-04-04
  • 詳解使用webpack打包編寫一個(gè)vue-toast插件

    詳解使用webpack打包編寫一個(gè)vue-toast插件

    本篇文章主要介紹了詳解使用webpack打包編寫一個(gè)vue插件,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2017-11-11
  • vue3使用element-plus搭建后臺(tái)管理系統(tǒng)之菜單管理功能

    vue3使用element-plus搭建后臺(tái)管理系統(tǒng)之菜單管理功能

    這篇文章主要介紹了vue3使用element-plus搭建后臺(tái)管理系統(tǒng)之菜單管理,使用element-plus el-tree組件快速開發(fā)樹形菜單結(jié)構(gòu),el-tree組件中filter-node-method事件便可以實(shí)現(xiàn)樹形菜單篩選過濾功能,需要的朋友可以參考下
    2022-04-04
  • vue實(shí)現(xiàn)頁面緩存功能

    vue實(shí)現(xiàn)頁面緩存功能

    這篇文章主要為大家詳細(xì)介紹了vue實(shí)現(xiàn)頁面緩存功能,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-10-10
  • vue組件內(nèi)部引入外部js文件的方法

    vue組件內(nèi)部引入外部js文件的方法

    這篇文章主要介紹了vue組件內(nèi)部引入外部js文件的方法,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-01-01
  • 如何在vite初始化項(xiàng)目中安裝scss以及scss的使用

    如何在vite初始化項(xiàng)目中安裝scss以及scss的使用

    今天想要給vite項(xiàng)目,添加全局的scss變量文件引用,這樣我們?cè)谑褂胹css變量和函數(shù)的時(shí)候就不需要每個(gè)組件都取引用了,下面這篇文章主要給大家介紹了關(guān)于如何在vite初始化項(xiàng)目中安裝scss以及scss使用的相關(guān)資料,需要的朋友可以參考下
    2022-10-10

最新評(píng)論