vue3之ref和reactive 响应式源码解析

原创
2020/09/28 15:20
阅读数 465

https://zhuanlan.zhihu.com/p/85978064
https://zhuanlan.zhihu.com/p/87409653

对于基本数据类型,函数传递或者对象解构时,会丢失原始数据的引用,换言之,我们没法让基本数据类型,或者解构后的变量(如果它的值也是基本数据类型的话),成为响应式的数据。

// 我们是永远没办法让`a`或`x`这样的基本数据成为响应式的数据的,Proxy也无法劫持基本数据。
const a = 1;
const { x: 1 } = { x: 1 }

 

但是有时候,我们确实就是想一个数字、一个字符串是响应式的,或者就是想利用解构的写法。那怎么办呢?只能通过创建一个对象,也即是源码中的Ref数据,然后将原始数据保存在Ref的属性value当中,再将它的引用返回给使用者。既然是我们自己创造出来的对象,也就没必要使用Proxy再做代理了,直接劫持这个value的get/set即可,这就是ref函数与Ref类型的由来。

不过单靠ref还没法解决对象解构的问题,它只是将基本数据保持在一个对象的value中,以实现数据响应式。对于对象的解构还需要另外一个函数:toRefs

export function toRefs<T extends object>(
  object: T
): { [K in keyof T]: Ref<T[K]> } {
  const ret: any = {}
  // 遍历对象的所有key,将其值转化为Ref数据
  for (const key in object) {
    ret[key] = toProxyRef(object, key)
  }
  return ret
}
function toProxyRef<T extends object, K extends keyof T>(
  object: T,
  key: K
): Ref<T[K]> {
  const v = {
    [refSymbol]: true,
    get value() {
      // 注意,这里没用到track
      return object[key]
    },
    set value(newVal) {
      // 注意,这里没用到trigger
      object[key] = newVal
    }
  }
  return v as Ref<T[K]>
}

通过遍历对象,将每个属性值都转成Ref数据,这样解构出来的还是Ref数据,自然就保持了响应式数据的引用

展开阅读全文
打赏
0
0 收藏
分享
加载中
更多评论
打赏
0 评论
0 收藏
0
分享
返回顶部
顶部