最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

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

 更新時間:2022年06月24日 15:16:14   作者:一個寫前端的  
這篇文章主要介紹了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'
/**
?*?
?* @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>

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

1. readonly API的使用

在我們傳遞給其他組件數(shù)據(jù)時,如果直接將響應式數(shù)據(jù)傳遞給子組件。子組件如果使用數(shù)據(jù)不規(guī)范,修改了父組件傳進來的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)容,但是不允許它們修改時,就可以使用 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. 響應式變量直接解構(gòu)會失去響應性

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

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

3. watchEffect 清除副作用

watchEffect API 可自動收集依賴項,當依賴項改變時觸發(fā)偵聽器函數(shù)。當我們在偵聽器函數(shù)執(zhí)行額外的副作用函數(shù),例如:發(fā)送網(wǎng)絡請求時。每當依賴性項變更都會發(fā)起一個新的網(wǎng)絡請求,那么上一次的網(wǎng)絡請求應該被取消掉。這個時候我們就可以清除上一次的副作用了。

setup() {
? ? const count = ref(0);
? ? const onChangeCount = () => {
? ? ? count.value++;
? ? };
? ? watchEffect((onInvalidate) => {
? ? ? // 偵聽器函數(shù)中需要發(fā)起網(wǎng)絡請求,用setTimeout模擬
? ? ? const timer = setTimeout(() => {
? ? ? ? console.log("請求成功啦");
? ? ? }, 2000);
? ? ? // 在偵聽器函數(shù)重新執(zhí)行時觸發(fā)onInvalidate函數(shù)
? ? ? onInvalidate(() => {
? ? ? ? // 在這個函數(shù)中清除請求
? ? ? ? clearTimeout(timer);
? ? ? ? console.log("onInvalidate 回調(diào)觸發(fā)");
? ? ? });
? ? ? // 自動收集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ù),并保存響應性。

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 是一個 { name: ?function mappedState (){...}, age: function mappedState (){...}, height: function mappedState (){...} } 這樣的對象
? ? ?*/
? ? 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() {
? ? // 數(shù)組用法
? ? 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 輔助函數(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兩個函數(shù)相似度很高,在進一下封裝

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

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

相關(guān)文章

  • vue路由教程之靜態(tài)路由

    vue路由教程之靜態(tài)路由

    這篇文章主要給大家介紹了關(guān)于vue路由教程之靜態(tài)路由的相關(guān)資料,文中通過示例代碼介紹的非常詳細,對大家學習或者使用vue具有一定的參考學習價值,需要的朋友們下面來一起學習學習吧
    2019-09-09
  • vue如何動態(tài)給img賦值

    vue如何動態(tài)給img賦值

    這篇文章主要介紹了vue如何動態(tài)給img賦值,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-06-06
  • 淺談VUE uni-app 常用API

    淺談VUE uni-app 常用API

    這篇文章主要介紹了uni-app 常用API,本文通過實例代碼給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2021-10-10
  • elementui之el-table如何通過v-if控制按鈕顯示與隱藏

    elementui之el-table如何通過v-if控制按鈕顯示與隱藏

    這篇文章主要介紹了elementui之el-table如何通過v-if控制按鈕顯示與隱藏問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2023-11-11
  • vue 使用 canvas 實現(xiàn)手寫電子簽名

    vue 使用 canvas 實現(xiàn)手寫電子簽名

    這篇文章主要介紹了vue 使用 canvas 實現(xiàn)手寫電子簽名功能,本文通過實例代碼給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2020-03-03
  • vue中各種deep的區(qū)別解析

    vue中各種deep的區(qū)別解析

    在Vue3中,推薦使用::deep作為深度選擇器,它比Vue2中的::v-deep語法更簡潔,::v-deep、::deep、:deep()、&gt;&gt;&gt;和/deep/都是用于穿透組件作用域的選擇器,但Vue3更傾向于使用::deep或:deep(),感興趣的朋友跟隨小編一起看看吧
    2024-10-10
  • vue實力踩坑?當前頁push當前頁無效的解決

    vue實力踩坑?當前頁push當前頁無效的解決

    這篇文章主要介紹了vue實力踩坑?當前頁push當前頁無效的解決方案,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-04-04
  • Vue2?this直接獲取data和methods原理解析

    Vue2?this直接獲取data和methods原理解析

    這篇文章主要為大家介紹了Vue2?this直接獲取data和methods原理解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-12-12
  • vue與iframe頁面數(shù)據(jù)互相通信的實現(xiàn)示例

    vue與iframe頁面數(shù)據(jù)互相通信的實現(xiàn)示例

    這篇文章主要給大家介紹了vue與iframe頁面數(shù)據(jù)互相通信的實現(xiàn)示例,文中通過代碼示例給大家介紹的非常詳細,對大家的學習或工作有一定的幫助,需要的朋友可以參考下
    2023-12-12
  • vue2結(jié)合element-ui的gantt圖實現(xiàn)可拖拽甘特圖

    vue2結(jié)合element-ui的gantt圖實現(xiàn)可拖拽甘特圖

    因為工作中要用到甘特圖,所以我在網(wǎng)上搜索可以用的甘特圖,搜索了好多,但是網(wǎng)上搜到大多數(shù)都很雞肋,不能直接使用,下面這篇文章主要給大家介紹了關(guān)于vue2結(jié)合element-ui的gantt圖實現(xiàn)可拖拽甘特圖的相關(guān)資料,需要的朋友可以參考下
    2022-11-11

最新評論

广丰县| 天长市| 邢台市| 临沂市| 永济市| 凉城县| 吉安市| 上思县| 长汀县| 龙江县| 海盐县| 石嘴山市| 米脂县| 隆回县| 徐汇区| 西乌| 张掖市| 察雅县| 顺昌县| 祥云县| 浙江省| 石泉县| 东海县| 梁河县| 益阳市| 清徐县| 章丘市| 桃园县| 莒南县| 内江市| 辽阳县| 徐闻县| 乌海市| 诏安县| 海城市| 连州市| 贵定县| 定兴县| 阜南县| 龙山县| 鲜城|