vue学习(7)vuex的辅助函数封装(基于vue3)

简介:

封装了 mapState,mapGetters,mapActions,mapMutations,用更灵活的方式来使用vuex,主要使用的是vuex的createNamespacedHelpers方法,此方法是帮助重写以特定模块为主的辅助函数

createNamespacedHelpers 在vuex@^3.1.1 及以上都有

文件截图:

 源码:

以下举个例子,模块名为index,模块里有自己的state等相关

1、store/index.ts

import { InjectionKey, App } from 'vue'
import { createStore, useStore as baseUseStore, Store } from 'vuex'
import { StateTypes } from './types'
import index from './modules/index'

// InjectionKey 将store安装到Vue应用程序时提供类型,将类型传递InjectionKey给useStore方法
// 定义注入类型
const key: InjectionKey> = Symbol()

const store = createStore({
  modules: {
    index
  }
})

export function useStore() {
  return baseUseStore(key)
}

export function setupStore(app: App): void {
  app.use(store, key)
}

export default store

2、store/types.ts

/** 模块类型 */
export interface StateTypes {
  index: any
}

/** state类型 */
export interface IndexStateType {
  requestCount: {
    count: number
  },
  [key: string]: any
}

/** getter类型 */
export interface GetterType {
  [key: string]: (state: IndexStateType) => any
}

3、store/modules/index.ts

import { Module, ActionTree, MutationTree, } from 'vuex'
import { IndexStateType, StateTypes, GetterType } from '../types'

const state: IndexStateType = {
  requestCount: {
    count: 0
  },
  a: 999
}

const getters: GetterType= {
  getCount(state) {
    return state.a
  }
}

const mutations: MutationTree = {
  increment(state: IndexStateType, clearFlag: boolean = false) {
    if (!clearFlag) {
      state.requestCount.count++
    } else {
      state.requestCount.count = 0
    }
  }
}

const actions: ActionTree = {
  increments({ dispatch, commit }) {
    commit('increment')
    // dispatch('xxmodule/xxx', xxx, { root: true })
  }
}

const index: Module = {
  namespaced: true,
  state,
  getters,
  mutations,
  actions
}

export default index

4、store/hooks.ts

import { createNamespacedHelpers } from 'vuex'
import { computed } from 'vue'
import {
  useStore
} from './index'

/**
 * 实际遍历函数
 * @param mapper 遍历属性名
 * @param mapFn 被调用的辅助函数
 * @param type true => Mutations, Actions; false => States, Getters
 * @returns
 */
function mapStore(props: string[] | string, mapStoreFcn: Function, type: boolean = false){
  const propsList = mapStoreFcn(props)
  const store = useStore()
  const storeState = {} as any
  Object.keys(propsList).forEach(item => {
    const fn = propsList[item].bind({$store: store})
    // Mutations, Actions 为方法,返回函数体, States, Getters 为计算属性,返回非响应式数据
    storeState[item] = type ? fn : computed(fn).value
  })
  return storeState
}

/**
 * state辅助函数
 * @param moduleName 模块名
 * @param mapper 属性数组 或者 单属性
 * @returns 
 */
export function useState(moduleName: string, props: string[] | string) {
  // 创建专属命名空间的store
  const store = createNamespacedHelpers(moduleName).mapState
  return mapStore(props, store)
}

/**
 * getters hook
 * @param moduleName 模块名
 * @param mapper 属性数组 或者 单属性
 * @returns 
 */
export function useGetters(moduleName: string, props: string[] | string){
  // 创建专属命名空间的store
  const store = createNamespacedHelpers(moduleName).mapGetters
  return mapStore(props, store)
}

export function useActions(moduleName: string, props: string[] | string){
  // 创建专属命名空间的store
  const store = createNamespacedHelpers(moduleName).mapActions
  return mapStore(props, store, true)
}

export function useMutations(moduleName: string, props: string[] | string){
  // 创建专属命名空间的store
  const store = createNamespacedHelpers(moduleName).mapMutations
  return mapStore(props, store, true)
}

调用方式:

useState,useGetters,useActions,useMutations都是传两个参数,第一参数为模块名,第二参数为数组,可以传单个或者多个,不过区别的是useState,useGetters返回的直接是非响应式对象值,而useActions,useMutations返回的是方法,可以自己去调用

import {
  ref
} from 'vue';

import {
  useState,
  useGetters,
  useActions,
  useMutations
} from '@/store/hooks'; 
export default function() {
  const page = ref(1)
  const state = useState('index', ['requestCount', 'a'])
  const getter = useGetters('index', ['getCount'])
  const actions = useActions('index', ['increments'])
  actions.increments()
  console.log(state.requestCount.count);
  
  return {
    page
  }
}

你可能感兴趣的:(vue学习,vue.js,学习,前端)