Vue3源码系列之ref、toRef及toRefs的实现
前⾔
ref和reactive的区别
reactive内部采⽤的proxy,ref内部采⽤的是defineProperty
ref也可以放对象,只是取值的时候需要多取⼀层,如果是对象⽤reactive更加合理
reactive你如果放普通类型,也就是⾮对象会直接返回,这个原因可以从我之前的博⽂中查
ref的出现就是因为reactive处理不了基本类型
Ref核⼼源码reactive 数组
第⼀步
源码⽬录下创建ref.ts⽂件,创建ref函数
我们接下来要做的第⼀步就是将传⼊的普通类型变成⼀个对象,核⼼⽅法是createRef
插⼀句,源码写到现在,是不是发现很多⽅法⾥⾯⼜调其它⽅法,包了⼀层,原因就是我们其它的api也可能⽤到,并且通过传递不同的参数去实现不同的功能。所以说Vue3源码基本上都是⾼阶函数+科⾥化
第⼆步
createRef⽅法接收两个参数,value和是否是浅的
它内部需要返回⼀个实例-RefImpl,把参数传进去
RefImpl类
然后利⽤类的属性访问器,取值的时候track来进⾏依赖收集,设置值的时候调⽤trigger去触发更新
复⽤了我们之前写reactive时封装的track和tringger⽅法
可能有⼈会问了,我⽂章开头的时候说ref底层是利⽤的defineProperty,那在哪⾥呢?其实我们刚才写的代码经过babel转化成es5代码就是defineProperty
然后我们再去处理下_value
当我们取值时取的就是_value
当我们更新值的时候去⽐较⼀下新值和⽼值是否有变化,如果有变化就把新值作为⽼值
同时我们还要去把_value给改了,改成newVal,最后再去触发更新
然后再去处理shallow,如果是深度需要把⾥⾯的都编程响应式的
在我们设置值的时候也要去考虑⼀下shallow
此时你是不是就明⽩了,如果ref传⼊多层对象,底层也是会去调⽤reactive去把它变成响应式
toRef核⼼源码
可以把⼀个对象的值转化成ref类型
内部也会产⽣⼀个实例,它⽤的类跟ref不是同⼀个类
ObjectRefImpl类
相当于我们将某⼀个key对应的值,转化为ref,就是暴露出⼀个属性的代理出去,并不会做其它事情,所以这个属性是否是响应式的,取决于代理的对象target是否是响应式的。
toRef的使⽤场景
当我们从⼀个reactive处理过的对象拿出来某个属性进⾏操作的时候,你去重新给拿出来的这个属性赋值,并不会产⽣什么效果,因为拿出来的值就仅仅是个字符串,不会是响应式的。所以我们为了防⽌拿出来的值是个字符串,我们需要⽤toRef做⼀层代理,让
假如说我想代理多个呢?toRefs就诞⽣了,不然你总不能⼀个⼀个去代理吧
toRefs核⼼源码
参数可能是对象也可能是数组
有时候我们想把reactive处理过的值结构出来,但是结构出来的数据就不是响应式的了,所以我们需要toRefs处理⼀下,相当于Vue⾃⼰写了个对象解构⽅法
再多唠叨⼀下toRefs的使⽤场景
我们这样做,在模板中必须得state.来取,不太友好,有点⿇烦,我想在模板中直接⽤,这个时候我们⽤toRefs
这样我们就可以在模板中直接⽤了
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论