vue3+ts 使用 vuex辅助函数(mapState,mapMutations,mapGetters,mapActions) 对函数进行二次封装

vue2中的使用方式

...mapState(["abc", "name"])
...mapState({
    
    
        name: state => state.name,
      })
 ...mapGetters(["allName"])
  ...mapGetters({
    
    
        allAge: "main/allAge",
      })
      
 ...mapMutations("app", ["setImageBgSrc"]), 
 ...mapMutations(["setname", "setabc"),
 
 ...mapActions(["getabc", "getList"]),
 ...mapActions({
    
    
        getB: "user/getB"
})

vue3 封装vuex辅助函数

本文辅助函数封装是参考 深入Vue3+TypeScript技术栈-coderwhy大神新课 视频学习改的
这里进行封装
vue3 中对于vuex的支持不是很好
使用hooks进行封装
目录结构如下:
在这里插入图片描述
index.ts

import {
    
     useGetters } from './useGetters'
import {
    
     useMutations } from './useMutations'
import {
    
     useState } from './useState'
import {
    
     useActions } from './useActions'

export {
    
     useGetters, useState, useMutations, useActions }

useMapper.ts

import {
    
     computed } from 'vue'
import {
    
     Computed, Mapper, MapperWithNamespace, useStore } from 'vuex'

export function useMapper(
  mapper: any,
  mapFn: Mapper<Computed> & MapperWithNamespace<Computed>,
  mapName:
    | 'mapMutations'
    | 'mapGetters'
    | 'mapState'
    | 'mapActions'
    | undefined = undefined
) {
    
    
  // 拿到store独享
  const store = useStore()

  // 获取到对应的对象的functions: {name: function, age: function}
  const storeStateFns = mapFn(mapper)

  // 对数据进行转换
  const storeState = {
    
    }
  Object.keys(storeStateFns).forEach((fnKey) => {
    
    
    const fn = storeStateFns[fnKey].bind({
    
     $store: store })
    if ((mapName && mapName === 'mapMutations') || mapName === 'mapActions') {
    
    
      // storeState[fnKey] = fn
      storeState[fnKey] = computed(() => {
    
    
        return fn
      }).value
    } else {
    
    
      storeState[fnKey] = computed(fn)
    }
  })

  return storeState
}

useActions.ts

import {
    
     mapActions, createNamespacedHelpers } from 'vuex'
import {
    
     useMapper } from './useMapper'

export function useActions(moduleName: any, mapper = undefined) {
    
    
  const mapName = 'mapActions'
  let mapperFn = mapActions
  if (moduleName && moduleName.length > 0) {
    
    
    mapperFn = createNamespacedHelpers(moduleName).mapActions
  } else {
    
    
    mapper = moduleName
  }

  return useMapper(mapper, mapperFn, mapName)
}


useGetters.ts

import {
    
     mapGetters, createNamespacedHelpers } from 'vuex'
import {
    
     useMapper } from './useMapper'

export function useGetters(moduleName: any, mapper = undefined) {
    
    
  let mapperFn = mapGetters
  if (typeof moduleName === 'string' && moduleName.length > 0) {
    
    
    mapperFn = createNamespacedHelpers(moduleName).mapGetters
  } else {
    
    
    mapper = moduleName
  }

  return useMapper(mapper, mapperFn)
}

useMutations.ts

import {
    
     mapMutations, createNamespacedHelpers } from 'vuex'
import {
    
     useMapper } from './useMapper'

export function useMutations(moduleName: any, mapper = undefined) {
    
    
  const mapName = 'mapMutations'
  let mapperFn = mapMutations
  if (moduleName && moduleName.length > 0) {
    
    
    mapperFn = createNamespacedHelpers(moduleName).mapMutations
  } else {
    
    
    mapper = moduleName
  }

  return useMapper(mapper, mapperFn, mapName)
}

useState.ts

import {
    
     mapState, createNamespacedHelpers } from 'vuex'
import {
    
     useMapper } from './useMapper'

export function useState(moduleName: any, mapper: any = undefined) {
    
    
  let mapperFn = mapState
  if (typeof moduleName === 'string' && moduleName.length > 0) {
    
    
    mapperFn = createNamespacedHelpers(moduleName).mapState
  } else {
    
    
    mapper = moduleName
  }

  return useMapper(mapper, mapperFn)
}

store目录

store目录 长这样 types 就不写了
在这里插入图片描述

index.ts

import {
    
     createStore } from 'vuex'
import main from './module/main/main'

const store = createStore({
    
    
  state() {
    
    
    return {
    
    
      rootCounter: 0
    }
  },
  getters: {
    
    
    // doubleRootCounter(state) {
    
    
    //   return state.rootCounter * 2
    // }
  },
  mutations: {
    
    
    increment(state) {
    
    
      state.rootCounter++
    }
  },
  modules: {
    
    
    main
  }
})

export default store

main.ts

import {
    
     Module } from 'vuex'
import {
    
     IRootState, optionsType } from '@/store/types'
import {
    
     mainStateType } from './types'

const mainModule: Module<mainStateType, IRootState> = {
    
    
  namespaced: true,
  state() {
    
    
    return {
    
    
      drawer: {
    
    
        wmsDrawerShow: true
      },
      abc: 123
    }
  },
  mutations: {
    
    
    // 设置子属性
    /**
     * @param state
     * @param data  修改的对象 如:{abc:123}
     */
    setMain(state, data) {
    
    
      for (const keyD of Object.keys(data)) {
    
    
        for (const keyS of Object.keys(state)) {
    
    
          if (keyS == keyD) {
    
    
            state[keyS] = data[keyD]
          }
        }
      }
    }
  },
  getters: {
    
    
    getabc(state) {
    
    
      return state.abc
    }
    // pageListData(state) {
    
    
    //   return (pageName: string) => {
    
    
    //     return (state as any)[`${pageName}List`]
    //   }
    // },
  },
  actions: {
    
    
    setWmsDrawerShow({
    
     commit }, payload: any) {
    
    
      commit('setMain', payload)
    }
  }
}

export default mainModule

组件调用辅助函数

import {
    
    
  useState,
  useMutations,
  useGetters,
  useActions
} from '../../hooks/vuexHooks'

const storeState: any = useState({
    
    
      wmsDrawerShow: (state: any) => state.main.drawer.wmsDrawerShow
    })
    const storeGetters: any = useGetters({
    
    
      getabc: 'main/getabc'
    })
    console.log('wmsDrawerShow', storeState.wmsDrawerShow.value)
    console.log('getabc', storeGetters.getabc.value)
    const storeMutations: any = useMutations({
    
    
      setMain: 'main/setMain'
    })
    const storeMutations2: any = useMutations(['increment'])
    const storeActions: any = useActions({
    
    
      setWmsDrawerShow: 'main/setWmsDrawerShow'
    })
    const {
    
     setMain } = storeMutations
    const {
    
     increment } = storeMutations2

    const {
    
     setWmsDrawerShow } = storeActions
    setTimeout(() => {
    
    
      increment()
      setMain({
    
    
        drawer: {
    
    
          wmsDrawerShow: false
        }
      })
      setWmsDrawerShow({
    
    
        abc: 456
      })
    }, 3000)

注意:当前封装 ts类型使用了很多any 使得书写代码是没有代码提示 如果按照vuex官网不使用辅助函数方式是有代码提示的 如各位有更好的封装方式 及ts类型的引入 请告知我,相互学习

结果

在这里插入图片描述
vue.js devtools 查看
在这里插入图片描述
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/weixin_43245095/article/details/123380948