前言
这是我参与「掘金日新计划 · 2 月更文挑战」的第 4 天,点击查看活动详情” 今天正式进入研究vue3源码的响应式部分。
正文
今天我们一起来看下Vue3是如何实现reactive的,reactive和ref是vue响应式那块比较核心的API,reactive的话传入的参数必须要是一个对象。
翻阅reactive源码,传入的参数必须要是一个对象,如果传入的参数是readonly,那么直接将target返回出去。反之,通过createReactiveObject这个方法创建一个响应式的Ojbect。查看这个方法在源码中的使用,会发现shallowReactive、readonly、shallowReadonly也是基于这个方法实现的,只是传入的参数不一样罢了。
查看这个方法,如图所示,其中参数包括target、isReadonly、baseHandlers等。继续翻源码会发现源码里面是用proxy去做一层拦截,然后Refleact去做取值操作。这样的好处是什么呢,其一,相比较vue2,它可以拦截数组的相关操作,而在vue2里面,是通过ojbect.defineProperty进行拦截的。其次,它不用去层层递归,从而性能损失太大。那么为啥proxy可以拦截数组的操作呢,因为proxy拦截的是整个对象,obj.defineProperty是对对象属性监听,循环对象,一个个属性监听。
接下来我们重点看下baseHandlers,查看其源码,里面主要包括get,set、deleteProperty等操作。其中get里面包括收集依赖的操作,set里面包括触发依赖的操作。其中get对应对的createGetter方法,set对应的createSetter方法。
打开createGetter方法,查看对应的代码实现,如下图所示,包括两个参数,其一是isReadonly,其二是shallow,shallowGet、readonlyGet等方法需要传入不同的参数即可。其中isReadonly表示是否是只读的,shallow表示是否只是表面的。到这里reactive的大致流程就分析清楚了。
在reactive源码文件里面还有像isReactive、isReadonly等一系列方法,主要是通过判断其ReactiveFlags的类型并将其转化成布尔值返回出去。
最后:
以上就是reactive的相关源码实现,reactive在响应式那块起到至关重要的作用,后期还会分享响应式的其他源码实现。