《Vuejs设计与实现》6.3 自动脱ref
在前文中,我们封装了toRefs
去解决响应式丢失的问题,但是又带来了一个新的问题,如何自动脱ref
?
比如我们把一个值用在模板里,我们其实是不需要写.value
的,我们假设有这样2句伪代码,如果我们不能实现自动脱ref
,那么我们是不是需要在模板中每个变量都写.value
,这样显然不对,vue3中也并不需要,我们来看看如何实现。
const div = <div>{{a.value}}</div>
const { a }= toRefs(props)
所谓自动ref
是指,如果访问一个对象的属性,这个对象是ref
,则直接返回.value
。我们可以通过proxy
实现这个功能.
const a = ref(0)
const proxyRef = (obj)=>new Proxy(obj,{
get(target,key,receiver){
const value = Reflect.get(target,key,receiver)
return value.__v_isRef ? value.value : value
}
})
const a2 = proxyRef(a)
经过前面的学习,proxy
大家都应该很熟练了,上面这个段代码应该几分钟就能写好。原理就是我们代理了,ref
的访问操作,然后当访问的时候,我们判断一下这个对象是不是ref
,这时候就用到了我们之前给ref
定义的那个属性了__v_isRef
,其实看到这段逻辑我是想到了unref
的。
当我们在模板中使用ref
的时候,我们还会赋值,比如
const btn = <button onClick="a=2">Test</button>
那么我们自然要再代理set
方法,方法和上面的get
类似,就不再赘述,文章结尾再把全部代码奉上。
其实,在vue3中很多地方都是使用了自动脱钩,比如在创建新的reactive
时,当我们把ref
传入reative
中时,就会自动脱ref
,这点好像在之前的代码中没有体现。
const a=ref(0)
const obj = reactive({a})
obj.a // 0
下来就是在模板中自动脱钩,事实上,vue3脱ref
的地方可能更早一点,应该在setup
的时候就会自动执行脱ref
了。
这样的设计就是为了方便用户,尽量减少我们写.value
时的心智负担。
ref
是一个比较简单的结构,我之前以为ref
是一套重写的响应系统,但是现在看来,ref
是最大限度的复用了reactive
,只是增加了一个自动脱ref
的方法罢了。
转载自:https://juejin.cn/post/7134667206536724517