一、Ref的定义
vue3.0中的响应式原理是基于proxy做的,而使用proxy的前提是,我们要代理的是对象而不是基本类型数据。如果我们用如下方式定义一个响应式的数据,count的改变是无法变监听拦截到的:
这时候,就需要ref来先讲基本类型包装成{value: 基本类型数据},然后再对这个包装对象进行响应式处理。
二、Ref类型的实现
第一版本:
最容易想到的实现方式如下:
简单解释下,首先定义一个Ref类型,这个类型的value可以是任意类型(any),然后再定义一个ref的函数,接受一个任意类型的参数T,再将T封装成Ref类型返回。由上图我们可以看到,我们输入了number类型的值,由泛型的反向推到我们可以知道,返回的count是Ref
第二版本:
考虑到ref嵌套的问题,我们期望直接通过count.value获取,而不是count.value.value.value.value。这时候我们需要对一版本进行改进。
步骤一:extends
对于改进,首先想到的是利用extends关键字进行条件判断:
由上图可是,对于ref函数的返回时,我们进行了条件判断,如果传入的参数是Ref类型,函数将原封不动返回这个Ref类型,否则需要将T包装成Ref类型再进行返回。
这样针对ref(ref(2))这种嵌套场景,首先内层的ref(2)返回的是Ref
步骤二: UnwrapRef
UnwrapRef
a.如果泛型T是Ref
b.如果泛型T不是Ref类型,则UnwrapRef类型为T
由上面的分析我们可以定义如下图的方式定义UnwrapRef:
由图可知
a.当T继承自Ref,我们都过索引类型'ref'取到了T extends Ref
这里用到了推断类型infer,其作用类似于正则匹配里面的捕获组,先提前捕获类型R,在后续的表达式(? R : T)中用到这个捕获类型,R可以是任意类型。所以这个表达是*的含义就是:当T继承自Ref
b.当T未继承自Ref,我们通过索引类型'other',直接返回类型T
另外我们还要考虑UnwrapRef
由上图可以看出,如果T是object类型,我们通过索引类型‘object’找到类型 {[K in keyof T] : UnwrapRef
其中keyof操作符是TS中用来获取对象的key值的集合,这样K就表示对象T的任意key值,而UnwrapRef
总结知识点:
1.keyof操作符 2.利用extends进行条件判断 3.infer类型推断 4.索引类型 5.泛型反向推到
参考文章by晨曦时梦见兮