Vue 3 之:弄清 ref reactive toRef toRefs

如题所述

第1个回答  2022-06-17

reactive 会对传入对象进行包裹,创建一个该对象的 Proxy 代理。它是源对象的响应式副本, 不等于原始对象 。它“深层”转换了源对象的所有嵌套 property,解包并维持其中的任何 ref 引用关系。
reactive API 很好地解决了 Vue2 通过 defineProperty 实现数据响应式时的缺陷。使用也非常简单:

当将 ref 分配给 reactive property 时,ref 将被自动解包,无需再用 .value 访问。

ref 函数用来将一项数据包装成一个响应式 ref 对象。它接收任意数据类型的参数,作为这个 ref 对象 内部的 value property 的值。之后可以用 ref对象.value 访问或更改这个值。
因为基础数据类型只能传递值而不是引用地址,将它包装在一个对象内,可以实现数据的响应式。

可以通过 isRef 判断变量是否是 Ref 对象。
如果将对象分配为 ref 值,则内部会通过 reactive 方法使该对象具有高度的响应式。

有时我们可能需要为 ref 的内部值指定复杂类型。想要简洁地做到这一点,我们可以在调用 ref 覆盖默认推断时传递一个泛型参数:

因为 ref 就是通过 reactive 包装了一个对象 ,然后将值传给该对象的 value 属性,这也就是为什么每次访问时我们都需要加上 .value 。可以简单地把 ref(obj) 理解为 reactive({ value: obj }) 。

toRef 函数可以为传入对象的某个属性新创建一个响应式引用 ref 。这个 ref 可以被传递,它会保持对其源 property 的响应式连接。
第一个参数为源对象,第二个参数为源对象中的属性名。

再通过个小 🌰 对比下 ref 和 toRef :

当你要将 prop 的某个 ref (即用 ref 包装的属性) 传递给复合函数时, toRef 很有用:

即使源 property 不存在, toRef 也会返回一个可用的 ref。这使得它在使用可选 prop 时特别有用,因为可选 prop 并不会被 toRefs 处理。

了解完 toRef 后,就很好理解 toRefs 了,其作用是生成一个新对象,内部 每个属性都指向 传入的对象的 相应 property 的响应式数据 ref
也就是说,新对象本身与原对象的无关联(指向新的引用地址),但它的所有属性却都与源对象的对应属性建立了响应性。
toRef 可以记成建立一个 ref 属性值的引用, toRefs 则是所有 ref 响应属性值的引用。

看下 🌰:
如果对响应式对象进行解构,被解构的两个 property 的响应性都会丢失。

可以用 toRefs 函数建立起与源对象的响应式关联:

实际开发中,比如需要解构 props,就可以这样操作来保证与 props 参数的响应式引用:

但如果 title 是可选 prop,则传入的 props 中可能没有 title 。这种情况下, toRefs 将不会为 title 创建一个 ref ,此时就需要用 toRef 替代它:

像上面这样做确保我们的侦听器能够 根据 title prop 的变化做出反应

当从 组合式函数 返回响应式对象时, toRefs 非常有用,这样消费组件就可以在不丢失响应性的情况下对返回的对象进行分解/扩散: