简介:
封装了 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<Store<StateTypes>> = Symbol()
const store = createStore<StateTypes>({
modules: {
index
}
})
export function useStore() {
return baseUseStore(key)
}
export function setupStore(app: App<Element>): 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<IndexStateType> = {
increment(state: IndexStateType, clearFlag: boolean = false) {
if (!clearFlag) {
state.requestCount.count++
} else {
state.requestCount.count = 0
}
}
}
const actions: ActionTree<IndexStateType, StateTypes> = {
increments({ dispatch, commit }) {
commit('increment')
// dispatch('xxmodule/xxx', xxx, { root: true })
}
}
const index: Module<IndexStateType, StateTypes> = {
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<number>(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
}
}