likes
comments
collection

《Vuejs设计与实现》6.3 自动脱ref

作者站长头像
站长
· 阅读数 14

在前文中,我们封装了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的方法罢了。

《Vuejs设计与实现》6.3 自动脱ref