关于前端:pinia源码四mapHelper-API源码解析

40次阅读

共计 5580 个字符,预计需要花费 14 分钟才能阅读完成。

前言

【pinia 源码】系列文章次要剖析 pinia 的实现原理。该系列文章源码参考pinia v2.0.14

源码地址:https://github.com/vuejs/pinia

官网文档:https://pinia.vuejs.org

本篇文章将剖析 mapHelper API 的实现。

应用

pinia提供了 Vuex 中的 mapStatemapActions 等一些辅助函数。这些函数的定义在 packages/pinia/src/mapHelpers.ts 中。

mapStore

应用 mapStore 获取残缺的store

import {mapStores} from 'pinia'

const useUserStore = defineStore('user', {// ...})
const useCartStore = defineStore('cart', {// ...})

export default {
  computed: {...mapStores(useCartStore, useUserStore)
  },

  methods: {async buyStuff() {if (this.userStore.isAuthenticated()) {await this.cartStore.buy()
      }
    },
  },
}

mapState、mapGetters、mapActions

应用 mapState,获取store.statestate.getter

mapGettersmapState 的别名。

应用mapAction,获取store.actions

export default {
  computed: {
    ...mapState(useCounterStore, {
      n: 'count',
      triple: store => store.n * 3,
      doubleN: 'double'
    })
  },
  created() {this.add()
    console.log(this.n) // 2
    console.log(this.doubleN) // 4
  },
  methods: {
    ...mapActions(useCounterStore, {add: 'increment',})
  }
}

export default {
  computed: {...mapState(useCounterStore, [ 'count', 'double'])
  },
  created() {this.add()
    console.log(this.count) // 2
    console.log(this.double) // 4
  },
  methods: {...mapActions(useCounterStore, [ 'add'])
  }
}

mapWritableState

mapState 类似,与 mapState 不同的是,通过 mapWritableState 取得的数据,能够间接对其进行批改。

export default defineComponent({
  name: 'Test',
  computed: {...mapWritableState(useCounterStore, [ 'n'])
  },
  methods: {handleClick() {this.n++}
  }
})

mapStore 源码

export function mapStores<Stores extends any[]>(...stores: [...Stores]
): _Spread<Stores> {
  // 如果接管的是个数组参数,进行提醒
  if (__DEV__ && Array.isArray(stores[0])) {
    console.warn(`[🍍]: Directly pass all stores to "mapStores()" without putting them in an array:\n` +
        `Replace\n` +
        `\tmapStores([useAuthStore, useCartStore])\n` +
        `with\n` +
        `\tmapStores(useAuthStore, useCartStore)\n` +
        `This will fail in production if not fixed.`
    )
    // 开发环境下 stores 取第一个值
    stores = stores[0]
  }

  // 返回一个对象
  return stores.reduce((reduced, useStore) => {// reduced 的 key 值:useStore.$id + mapStoreSuffix(默认 Store,可应用 setMapStoreSuffix 进行批改)
    reduced[useStore.$id + mapStoreSuffix] = function (this: ComponentPublicInstance) {
      // 应用 useStore 获取 store,在组件中可通过 this.$pinia 获取 pinia
      return useStore(this.$pinia)
    }
    return reduced
  }, {} as _Spread<Stores>)
}

mapStores可接管多个 useStore 函数。

mapStores会对参数进行校验,如果传入的第一个参数为数组,那么在开发环境下会进行提醒,并将数组中的第一个值赋给 stores,以保障开发环境下可能运行。而后返回一个对象,该对象通过stores.reduce 生成,对象的 key 值是由 useStore.$id + mapStoreSuffix 组成,对应的 value 是个函数,在函数中会调用useStore(this.$pinia),返回其后果。

mapState、mapGetters 源码

export function mapState<
  Id extends string,
  S extends StateTree,
  G extends _GettersTree<S>,
  A
>(
  useStore: StoreDefinition<Id, S, G, A>,
  keysOrMapper: any
): _MapStateReturn<S, G> | _MapStateObjectReturn<Id, S, G, A> {return Array.isArray(keysOrMapper)
    ? keysOrMapper.reduce((reduced, key) => {reduced[key] = function (this: ComponentPublicInstance) {return useStore(this.$pinia)[key]
        } as () => any
        return reduced
      }, {} as _MapStateReturn<S, G>)
    : Object.keys(keysOrMapper).reduce((reduced, key: string) => {reduced[key] = function (this: ComponentPublicInstance) {const store = useStore(this.$pinia)
          const storeKey = keysOrMapper[key]
          return typeof storeKey === 'function'
            ? (storeKey as (store: Store<Id, S, G, A>) => any).call(this, store)
            : store[storeKey]
        }
        return reduced
      }, {} as _MapStateObjectReturn<Id, S, G, A>)
}

export const mapGetters = mapState

mapState能够承受两个参数:useStore(一个 useStore 函数)、keysOrMapper(一个 key 列表,或 map 对象)。

mapState会返回一个对象,这个对象的 key 值是通过 keysOrMapper 取得的。如果传入 keysOrMapper 是数组,返回对象的 key 就是 keysOrMapper 中的元素,key对应的值是个获取 store[key] 的函数。如果 keysOrMapper 是个对象,返回对象的 keykeysOrMapper中的 keykey 对应的值依据 keysOrMapper[key] 的类型有所区别,如果 keysOrMapper[key]function,返回后果中对应 key 的值是一个返回 keysOrMapper[key].call(this, store) 的函数,否则 key 对应的是个返回 store[keysOrMapper[key]] 的函数。

mapGettersmapState

mapActions 源码

export function mapActions<
  Id extends string,
  S extends StateTree,
  G extends _GettersTree<S>,
  A,
  KeyMapper extends Record<string, keyof A>
>(
  useStore: StoreDefinition<Id, S, G, A>,
  keysOrMapper: Array<keyof A> | KeyMapper
): _MapActionsReturn<A> | _MapActionsObjectReturn<A, KeyMapper> {return Array.isArray(keysOrMapper)
    ? keysOrMapper.reduce((reduced, key) => {reduced[key] = function (
          this: ComponentPublicInstance,
          ...args: any[]) {return useStore(this.$pinia)[key](...args)
        }
        return reduced
      }, {} as _MapActionsReturn<A>)
    : Object.keys(keysOrMapper).reduce((reduced, key: keyof KeyMapper) => {reduced[key] = function (
          this: ComponentPublicInstance,
          ...args: any[]) {return useStore(this.$pinia)[keysOrMapper[key]](...args)
        }
        return reduced
      }, {} as _MapActionsObjectReturn<A, KeyMapper>)
}

mapActions能够承受两个参数:useStore(一个 useStore 函数)、keysOrMapper(一个 key 列表,或 map 对象)。

mapActions返回一个对象。对象中的键通过 keysOrMapper 取得,如果 keysOrMapper 是个数组,那么 key 是数组中的元素,对应的值是函数,这个函数返回对应 store[key]() 的返回值。如果 keysOrMapper 是个对象,那么对象中键就是 keysOrMapper 中的键,对应的值是个函数,这个函数返回 store[keysOrMapper[key]]() 的返回值。

mapWritableState 源码

export function mapWritableState<
  Id extends string,
  S extends StateTree,
  G extends _GettersTree<S>,
  A,
  KeyMapper extends Record<string, keyof S>
>(
  useStore: StoreDefinition<Id, S, G, A>,
  keysOrMapper: Array<keyof S> | KeyMapper
): _MapWritableStateReturn<S> | _MapWritableStateObjectReturn<S, KeyMapper> {return Array.isArray(keysOrMapper)
    ? keysOrMapper.reduce((reduced, key) => {reduced[key] = {get(this: ComponentPublicInstance) {return useStore(this.$pinia)[key]
          },
          set(this: ComponentPublicInstance, value) {return (useStore(this.$pinia)[key] = value as any)
          },
        }
        return reduced
      }, {} as _MapWritableStateReturn<S>)
    : Object.keys(keysOrMapper).reduce((reduced, key: keyof KeyMapper) => {reduced[key] = {get(this: ComponentPublicInstance) {return useStore(this.$pinia)[keysOrMapper[key]]
          },
          set(this: ComponentPublicInstance, value) {return (useStore(this.$pinia)[keysOrMapper[key]] = value as any)
          },
        }
        return reduced
      }, {} as _MapWritableStateObjectReturn<S, KeyMapper>)
}

mapWritableState实现过程与 mapState 类似,只不过 mapWritableState 返回后果中的 value 是个对象,对象中有 getset 函数,通过设置 set 函数,用户就能够批改对应的state

总结

mapStoresmapStatemapActions等辅助函数会在外部通过调用 useStore(在useStore 调用时会传入 this.$piniathis 为组件实例,这也是为什么辅助函数不能用在 setup 中,因为 setup 中是无奈获取组件实例)获取 store,而后在store 中获取对应属性。

正文完
 0