ref的实现原理
一句话总结: ref本身是个函数,该函数返回一个createRef函数,createRef函数又返回一个“经过类RefImpl实例化”的对象。
详情介绍: ref函数接收我们传入的一个简单类型或复杂类型value,后又将value传递给createRef函数,createRef函数先判断value是不是ref对象,是就直接返回该ref对象,直接结束函数,不是则返回类RefImpl实例化的对象。类RefImpl中接收我们传入的value,在构造函数中对value进行判断,当value是复杂类型时,将使用reactive对value进行响应式,并把返回的值赋值给类RefImpl的公共变量_value。当value是简单类型时,直接将value赋值给类RefImpl的公共变量_value。类RefImpl中还有使用set get关键字方法名为value来定义的getter setter方法,利用getter、setter方法可达到响应式的作用。
- getter方法
使用obj.value的方式可访问到getter方法,getter方法除了返回_value值外,还使用了trackRefValue方法收集依赖,那trackRefValue方法是怎么收集依赖的呢?在getter方法中调用trackRefValue方法并把this传过去,this是类Refmpl的实例对象,trackRefValue方法中又调用了trackEffects函数把实例对象的dep变量传过去,后把依赖添加到dep中,其中dep是一个Set类型。 - setter方法
使用obj.value设置值时可访问到setter方法,setter方法有一个参数,该参数表示设置的新值newVal,setter方法会先判断新旧值是否有变化,有变化时才去更新"最新的未响应式过的_rawValue和最新的响应式_value的值",这里_value值会先使用toReactive函数过滤一遍,toReactive函数是判断值是复杂类型还是简单类型,是简单类型直接返回,是复杂类型要先reactive响应式过再返回。最后再调用triggerRefValue方法触发依赖,那triggerRefValue方法是怎么触发依赖的呢?getter方法调用triggerRefValue方法时会把this也是实例对象传递过去,triggerRefValue方法接收实例对象后,调用triggerEffects方法把实例对象的dep传进去,然后遍历dep变量调用triggerEffect方法再触发run()方法一起触发所有依赖。
RefImpl类
1、在vue3中ref和reactive有什么不同?
reactive只能对复杂类型进行响应式,因为reactive内部使用的proxy,proxy只能接收复杂类型,ref能对复杂类型和简单类型进行响应式,当数据是复杂类型时,使用reactive进行响应,当数据是简单类型时,使用类的setter getter方法进行响应。