前言

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

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

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

本篇文章将剖析storeToRefs的实现。

应用

应用storeToRefs创立一个对象,该对象蕴含store中的所有stategetter及通过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环境,间接应用toRefsstore转换为一个一般对象;如果不是vue2环境,首先获取store的原始对象,而后遍历原始对象的键值,在遍历过程中,只会解决refref类型的值包含store中的stategettergetter会被转为计算属性)与reactive类型的值,对于符合条件的值,会将这些值转为ref类型的值,而后将其复制到一个新的对象中refs中,最初返回refs