Vue.js ref、toRef和toRef之间有什么区别

Vue.js ref、toRef和toRef之间有什么区别,vue.js,vue-component,vuejs3,vue-composition-api,vue-reactivity,Vue.js,Vue Component,Vuejs3,Vue Composition Api,Vue Reactivity,我刚刚开始使用VUE3和CompositionAPI 我想知道ref、toRef和toRefs之间的区别是什么?Vue 3ref A是Vue 3中反应性的一种机制。想法是将一个非对象包装在一个反应性对象中: 获取一个内部值并返回一个被动的、可变的ref对象。ref对象有一个指向内部值的属性.value reactive 对于自然对象,不需要ref环绕,因为它已经是一个对象。它只需要以下功能(ref也有此功能): const state=无功({ 傅:1,, 酒吧:2间 }) 但该对象的属性不是

我刚刚开始使用VUE3和CompositionAPI

我想知道
ref
toRef
toRefs
之间的区别是什么?

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

获取一个内部值并返回一个被动的、可变的ref对象。ref对象有一个指向内部值的属性
.value

reactive
对于自然对象,不需要ref环绕,因为它已经是一个对象。它只需要以下功能(ref也有此功能):

const state=无功({
傅:1,,
酒吧:2间
})
但该对象的属性不是自然的参照。这意味着,如果要复制属性,它将失去与其父对象的反应性/连接。这是
toRef
有用的地方

toRef
将单个
被动
对象属性转换为保持其与父对象连接的ref:

const state=无功({
傅:1,,
酒吧:2间
})
const fooRef=toRef(状态为“foo”)
/*
fooRef:Ref,
*/
toRefs
将所有特性转换为具有参照特性的普通对象:

const state=无功({
傅:1,,
酒吧:2间
})
const stateAsRefs=toRefs(状态)
/*
{
foo:Ref,
酒吧:参考
}
*/

被动的

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

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

  • state.foo
    是被动的(可用于模板、计算和监视)
  • state.foo.bar
    是被动的
  • state.baz
    state.foo.baz
    state.foo.bar.baz
    也都是被动的,即使
    baz
    在任何地方都不存在
这是因为
reactive
不仅创建一个顶级代理对象,它还递归地将所有嵌套对象转换为reactive代理,并且此过程在运行时继续发生,即使是动态创建的子对象也是如此。因此,您还可以在一个单独的变量中执行
const foo=state.foo
,并期望反应性能够正常工作
foo
。反应的力量来自代理对象

但是,始终存在需要注意的边缘情况:

  • 只有存在嵌套对象时,才能递归创建嵌套代理。如果给定属性不存在,或者该属性存在但不是对象,则无法在该属性上创建代理。例如,
    const baz=state.baz
    baz
    变量和
    const bar=state.foo.bar
    bar
    变量均不起作用。为了明确起见,它的意思是您可以在模板/computed/watch中使用
    state.baz
    state.foo.bar
    ,但不能使用上面创建的
    baz
    bar
  • 如果将嵌套代理提取到变量,则它将与其原始父级分离。通过一个例子可以更清楚地说明这一点。下面的第二个赋值(
    state.foo={bar:3}
    )不会破坏
    foo
    的反应性,但是
    state.foo
    将是一个新的代理对象,而
    foo
    变量仍然指向原始代理对象
  • ref
    toRef
    解决了一些边缘情况

    ref

    ref
    基本上是
    reactive
    ,它也适用于原语。我们仍然无法将JS原语转换为代理对象,因此
    ref
    始终将提供的参数
    X
    包装为形状
    {value:X}
    的对象。不管X是否为基本体,“装箱”总是发生。如果一个对象被赋予
    ref
    ref
    在装箱后内部调用
    reactive
    ,因此结果也是深度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。该属性可以是最初不存在的属性,也可以是其值为基元的属性

    在相同的示例中,状态定义为
    const state=reactive({foo:{bar:1}})

    • const foo=toRef(state,'foo')
      const foo=state.foo
      非常相似,但有两个区别:
    • foo
      是一个
      ref
      ,因此需要在js中执行
      foo.value
    • 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
    

    详细解释,谢谢@Xinchao!对于toRef,行“至参考
    const state = reactive({...});
    return {...state}; // will not work, destruction removes reactivity 
    return toRefs(state); // works