共计 5580 个字符,预计需要花费 14 分钟才能阅读完成。
前言
【pinia 源码】系列文章次要剖析 pinia
的实现原理。该系列文章源码参考pinia v2.0.14
。
源码地址:https://github.com/vuejs/pinia
官网文档:https://pinia.vuejs.org
本篇文章将剖析 mapHelper API
的实现。
应用
pinia
提供了 Vuex
中的 mapState
、mapActions
等一些辅助函数。这些函数的定义在 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.state
及state.getter
。
mapGetters
为 mapState
的别名。
应用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
是个对象,返回对象的 key
是keysOrMapper
中的 key
,key
对应的值依据 keysOrMapper[key]
的类型有所区别,如果 keysOrMapper[key]
是function
,返回后果中对应 key
的值是一个返回 keysOrMapper[key].call(this, store)
的函数,否则 key
对应的是个返回 store[keysOrMapper[key]]
的函数。
mapGetters
同mapState
。
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
是个对象,对象中有 get
、set
函数,通过设置 set
函数,用户就能够批改对应的state
。
总结
mapStores
、mapState
、mapActions
等辅助函数会在外部通过调用 useStore
(在useStore
调用时会传入 this.$pinia
,this
为组件实例,这也是为什么辅助函数不能用在 setup
中,因为 setup
中是无奈获取组件实例)获取 store
,而后在store
中获取对应属性。