微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

ref、toRef 和 toRefs 之间有什么区别 Vue 3 refreactivetoReftoRefs

如何解决ref、toRef 和 toRefs 之间有什么区别 Vue 3 refreactivetoReftoRefs

我刚刚开始使用 Vue 3 和 Composition API。

我想知道 reftoReftoRefs 之间有什么区别?

解决方法

Vue 3 ref

ref 是 Vue 3 中的一种反应机制。这个想法是将一个非对象包装在一个 reactive 对象中:

接受一个内部值并返回一个反应性和可变的 ref 对象。 ref 对象具有指向内部值的单个属性 .value

reactive

对于自然物体,不需要 ref 包装,因为它已经是一个物体。它只需要 reactive 功能(引用也有):

const state = reactive({
  foo: 1,bar: 2
})

但是这个对象的属性自然不是引用。这意味着如果您要复制一个属性,它将失去与父对象的反应性/连接。这就是 toRef 有用的地方。

toRef

toRef 将单个 reactive 对象属性转换为保持与父对象连接的引用:

const state = reactive({
  foo: 1,bar: 2
})

const fooRef = toRef(state,'foo')
/*
fooRef: Ref<number>,*/

toRefs

toRefs所有的属性转换为具有引用属性的普通对象:

const state = reactive({
  foo: 1,bar: 2
})

const stateAsRefs = toRefs(state)
/*
{
  foo: Ref<number>,bar: Ref<number>
}
*/
,

反应式

reactive 基于给定的对象创建一个深度响应式代理对象。代理对象看起来与给定的普通对象完全相同,但任何变化,无论多深,都是反应性的——甚至包括添加和删除的属性。重要的是 reactive 只能处理对象,不能处理基元。

例如,const state = reactive({foo: {bar: 1}}) 表示:

  • state.foo 是响应式的(可用于模板、计算和监视)
  • state.foo.bar 是被动的
  • state.bazstate.foo.bazstate.foo.bar.baz 也是响应式的,即使 baz 尚未在任何地方存在

这可能是因为 reactive 不仅创建了一个单一的顶级代理对象,它还递归地将所有嵌套的对象转换为反应式代理,并且这个过程在运行时继续发生,即使对于在飞。因此,您还可以在单​​独的变量中执行 const foo = state.foo 并期望反应性消除 foo。反应性的力量来自于 Proxy 对象。

然而,总有一些边缘情况需要注意:

  1. 嵌套代理的递归创建只能在存在嵌套对象时发生。如果给定的属性不存在,或者它存在但不是对象,则不能在该属性上创建代理。例如。反应性不适用于 bazconst baz = state.baz 变量,也不适用于 barconst bar = state.foo.bar 变量。明确地说,这意味着您可以在模板/计算/手表中使用 state.bazstate.foo.bar,但不能在上面创建的 bazbar 中使用。立>
  2. 如果您将嵌套代理提取到变量中,则它会与其原始父代分离。可以通过一个例子更清楚地说明这一点。下面的第二个赋值 (state.foo = {bar: 3}) 不会破坏 foo 的反应性,但是 state.foo 将是一个新的代理对象,而 foo 变量仍然指向原始代理对象.
const state = reactive({foo: {bar: 1}});
const foo = state.foo;

state.foo.bar = 2;
foo.bar === 2; // true,because foo is reactive

state.foo = {bar: 3};
foo.bar === 3; // false,foo.bar will still be 2;  

reftoRef 解决了其中一些边缘情况。

参考

ref 几乎是同样适用于原语的 reactive。我们仍然无法将 JS 原语转换为 Proxy 对象,因此 ref 总是将提供的参数 X 包装成形状为 {value: X} 的对象。 X 是否是原始的并不重要,“装箱”总是发生。如果将对象赋予 ref,则 ref 在装箱后内部调用 reactive,因此结果也是深度反应性的。实践中的主要区别在于,在使用 ref 时,您需要记住在 js 代码中调用 .value。在您的模板中,您不必调用 .value,因为 Vue 会自动在模板中解包 ref。

const count = ref(1);
const objCount = ref({count: 1});

count.value === 1; // true
objCount.value.count === 1; // true

toRef

toRef 旨在将反应式对象的属性转换为 ref。您可能想知道为什么这是必要的,因为反应式对象已经是深度反应式的。 toRef 用于处理为 reactive 提到的两个边缘情况。总之,toRef 可以将反应式对象的任何属性转换为链接到其原始父级的 ref。该属性可以是最初不存在的属性,也可以是原始值。

在将 state 定义为 const state = reactive({foo: {bar: 1}}) 的同一示例中:

  • const foo = toRef(state,'foo')const foo = state.foo 非常相似,但有两点不同:
    1. foo 是一个 ref 所以你需要在 js 中做 foo.value;
    2. foo 链接到其父级,因此重新分配 state.foo = {bar: 2} 将反映在 foo.value
  • const baz = toRef(state,'baz') 现在可以使用了。

toRefs

toRefs 是一种实用方法,用于销毁反应式对象并将其所有属性转换为 ref:

const state = reactive({...});
return {...state}; // will not work,destruction removes reactivity 
return toRefs(state); // works

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。