Vue3源码系列之ref、toRef及toRefs的实现

前言 ref和reactive的区别
  • reactive内部采用的proxy,ref内部采用的是defineProperty
  • ref也可以放对象,只是取值的时候需要多取一层,如果是对象用reactive更加合理
  • reactive你如果放普通类型,也就是非对象会直接返回,这个原因可以从我之前的博文中查找
  • ref的出现就是因为reactive处理不了基本类型
  Ref核心源码   第一步 源码目录下创建ref.ts文件,创建ref函数   我们接下来要做的第一步就是将传入的普通类型变成一个对象,核心方法是createRef Vue3源码系列之ref、toRef及toRefs的实现   插一句,源码写到现在,是不是发现很多方法里面又调其它方法,包了一层,原因就是我们其它的api也可能用到,并且通过传递不同的参数去实现不同的功能。所以说Vue3源码基本上都是高阶函数+科里化   第二步 createRef方法接收两个参数,value和是否是浅的 Vue3源码系列之ref、toRef及toRefs的实现   它内部需要返回一个实例-RefImpl,把参数传进去 Vue3源码系列之ref、toRef及toRefs的实现   RefImpl类 Vue3源码系列之ref、toRef及toRefs的实现   然后利用类的属性访问器,取值的时候track来进行依赖收集,设置值的时候调用trigger去触发更新 Vue3源码系列之ref、toRef及toRefs的实现 复用了我们之前写reactive时封装的track和tringger方法   可能有人会问了,我文章开头的时候说ref底层是利用的defineProperty,那在哪里呢?其实我们刚才写的代码经过babel转化成es5代码就是defineProperty   然后我们再去处理下_value Vue3源码系列之ref、toRef及toRefs的实现   当我们取值时取的就是_value Vue3源码系列之ref、toRef及toRefs的实现   当我们更新值的时候去比较一下新值和老值是否有变化,如果有变化就把新值作为老值 Vue3源码系列之ref、toRef及toRefs的实现   同时我们还要去把_value给改了,改成newVal,最后再去触发更新 Vue3源码系列之ref、toRef及toRefs的实现   然后再去处理shallow,如果是深度需要把里面的都编程响应式的 Vue3源码系列之ref、toRef及toRefs的实现Vue3源码系列之ref、toRef及toRefs的实现   在我们设置值的时候也要去考虑一下shallow Vue3源码系列之ref、toRef及toRefs的实现   此时你是不是就明白了,如果ref传入多层对象,底层也是会去调用reactive去把它变成响应式     toRef核心源码 可以把一个对象的值转化成ref类型   内部也会产生一个实例,它用的类跟ref不是同一个类 Vue3源码系列之ref、toRef及toRefs的实现   ObjectRefImpl类 Vue3源码系列之ref、toRef及toRefs的实现 相当于我们将某一个key对应的值,转化为ref,就是暴露出一个属性的代理出去,并不会做其它事情,所以这个属性是否是响应式的,取决于代理的对象target是否是响应式的。   toRef的使用场景 当我们从一个reactive处理过的对象拿出来某个属性进行操作的时候,你去重新给拿出来的这个属性赋值,并不会产生什么效果,因为拿出来的值就仅仅是个字符串,不会是响应式的。所以我们为了防止拿出来的值是个字符串,我们需要用toRef做一层代理,让   假如说我想代理多个呢?toRefs就诞生了,不然你总不能一个一个去代理吧   toRefs核心源码 参数可能是对象也可能是数组 Vue3源码系列之ref、toRef及toRefs的实现   有时候我们想把reactive处理过的值结构出来,但是结构出来的数据就不是响应式的了,所以我们需要toRefs处理一下,相当于Vue自己写了个对象解构方法   再多唠叨一下toRefs的使用场景 Vue3源码系列之ref、toRef及toRefs的实现 我们这样做,在模板中必须得state.来取,不太友好,有点麻烦,我想在模板中直接用,这个时候我们用toRefs Vue3源码系列之ref、toRef及toRefs的实现 这样我们就可以在模板中直接用了  
上一篇:响应式编程(Reactive Programming)


下一篇:框架 Spring Boot 2.0深度实践-初遇Spring Boot 1-3 Springboot2.0新特性