前言
【pinia源码】系列文章主要分析pinia
的实现原理。该系列文章源码参考pinia v2.0.14
。
源码地址:https://github.com/vuejs/pinia
本篇文章将分析storeToRefs
的实现。
使用
使用storeToRefs
创建一个对象,该对象包含store
中的所有state
、getter
及通过plugin
扩展的state
。
当使用store
的过程中,如果直接对store
进行解构,会破坏数据的响应,所以pinia
提供了storeToRefs
用来进行解构。
import { storeToRefs } from 'pinia'
import { useCounterStore } from '@/store/counterStore'
export default {
setup() {
const counterStore = useCounterStore()
// 可以解构actions
const { increment } = counterStore
const { count } = storeToRefs(counterStore)
return {
count,
increment,
}
}
}
storeToRefs
storeToRefs
接收一个store
参数。
export function storeToRefs<SS extends StoreGeneric>(
store: SS
): ToRefs<
StoreState<SS> & StoreGetters<SS> & PiniaCustomStateProperties<StoreState<SS>>
> {
// See https://github.com/vuejs/pinia/issues/852
// It's easier to just use toRefs() even if it includes more stuff
if (isVue2) {
// 如果是vue2直接返回toRefs(store),尽管其中包含很多methods
return toRefs(store)
} else { // 非vue2环境,会过滤store中的非ref或reactive对象
// store的原始对象
store = toRaw(store)
const refs = {} as ToRefs<
StoreState<SS> &
StoreGetters<SS> &
PiniaCustomStateProperties<StoreState<SS>>
>
for (const key in store) {
const value = store[key]
if (isRef(value) || isReactive(value)) {
// 使用toRef获取一个新的ref
refs[key] =
toRef(store, key)
}
}
return refs
}
}
首先判断是否为vue2
环境,如果是vue2
环境,直接使用toRefs
将store
转换为一个普通对象;如果不是vue2
环境,首先获取store
的原始对象,然后遍历原始对象的键值,在遍历过程中,只会处理ref
(ref
类型的值包括store
中的state
与getter
,getter
会被转为计算属性)与reactive
类型的值,对于符合条件的值,会将这些值转为ref
类型的值,然后将其复制到一个新的对象中refs
中,最后返回refs
。
网友评论