6个方面梳理ref和reactive的区别

1.基元值

ref()和reactive()处理不同的基元值:字符串、数字、布尔值、null和undefined。

1.1 ref()

refs()存储基元值和对象:

在上面的例子中,ref(0)创建了一个存储基元值的ref。

同样,ref({count:0})创建了一个存储纯JavaScript对象的ref。

1.2 reactive()

另一方面,reactive()不存储基元,而只存储对象:

使用基元值调用reactive(0)是不正确的。如果您需要生成反应基元值,那么ref(0)就是一种方法。

reactive()只适用于对象的原因是Vue的reactive实现。Vue使用代理截取对象的属性更改。代理不适用于基元。

尽管如此,用对象初始化的reactive({count:0})是完全有效的,并创建了一个reactive对象。

总结:

ref()可以存储基元值,而reactive()不能。

2.访问无功数据

第二个区别是如何访问存储在ref()和reactive()中的数据。

2.1 ref()

ref()数据,无论是基元值还是对象,都是通过一个特殊属性访问的。value:

numberRef.value是从引用numberRef访问基元值的方式。

<ref>.value是所有ref上可用的特殊属性,用于读取或更新ref值。

此外,objectRef.value.count是如何访问引用中对象的属性的。

请注意,在模板内部,您不必使用.value来访问ref值:它们是自动展开的。

在插值{{numberRef}}中,ref是自动展开的。

2.2 reactive()

另一方面,reactive()数据是直接访问的:

访问使用reactive({count:0})创建的reactive数据不需要额外的语法,而是直接完成的:objectReactive.count。

reactive(originalObject)返回的reactive对象是originalObject的代理对象。这意味着反应对象具有与原始对象相同的属性(也就是具有相同的接口)。

总结:

ref()数据使用value属性访问(异常:在模板中,ref是自动展开的),而reactive()数据则直接访问。

3.重新分配数据

ref()是使用.value属性访问和更新的,而reactive()是原始对象的代理。因此,ref()可以重新分配给一个新对象,而reactive()不能。

 

ref()

将ref()的值完全重新分配为新值是完全有效的:

在挂载后完全替换ref值objectRef.value={count:1}反映在输出中。保持反应性。

reactive()

但是,完全重新分配reactive()对象是不可能的:

安装后完全替换反应对象值objectReactive={count:1}并没有反映在输出中。这样做会破坏objectReactive的反应性。

总结:

ref()值可以完全重新分配给一个新对象,而reactive()不能。

4.类型化

ref()

通过.value属性访问ref数据的一个直接后果是如何键入ref。

要注释引用,您需要使用特殊类型的引用,可从vue库导入:

Ref<number>是一种类型,表示持有数字的Ref。

例如,如果要将ref指定为可组合的ref数,请确保使用ref<V>类型(其中V是值的类型)来注释refref数:

reactive()

另一方面,reactive()返回的reactive数据被类型化为初始对象:

reactive({count:0})返回类型为{count:number}的对象。反应对象通常保持原始对象的类型。

但有一个例外——如果反应对象包含引用,那么这些引用将被展开。

即使反应对象是{count:ref(0)},返回的类型仍然是{count:number}。这一切都是因为reactive()会自动打开在reactive对象中找到的refs。

总结:

ref返回的ref(值:T)的类型为ref,而reactive返回的reactive对象(对象:T)为T类型(异常:reactive中的ref被展开)。

5.监视

watch()监视反应数据的变化。ref()和reactive()的watch()的默认行为不同。

ref()

watch()确定ref的.value属性是否已更改:

每次单击“增加”按钮,您都会在控制台中看到消息“已更改!”。watch(count,callback)在每次countNumberRef.value更改时调用callback。

但是watch()是否监视存储在ref()中的对象的深层变化?

然而,这一次,如果您单击“增加”按钮,控制台中将不会出现任何消息!结论是watch()默认情况下不会深入观察refs。

然而,当countObjectRef.value.count发生变化时,DOM仍然会更新:这意味着ref中的对象对于渲染的输出仍然是被动的。

当然,如果你让watch()深入观察裁判,它的工作原理是完全深入观察:

reactive()

在监视反应对象的情况下,watch()始终执行深度监视(即使您没有指示{deep:true})选项。

每次单击“增加”按钮,您都会在控制台中看到消息“已更改!”。每当countObjectReactive的任何属性(甚至是深层属性)发生变化时,watch(countObjectReactor,callback)都会调用callback。

 

总结:

watch()默认情况下只监视ref()的直接.value更改,同时对reactive()对象进行深度监视。

6.用

虽然没有严格的规则,但在某些情况下,使用特定的反应性函数是可取的:

1.如果您需要一个反应基元值,那么使用ref()是正确的选择。

2.如果您需要一个反应值对象(一个属性通常不变的对象),那么使用ref()是一个不错的选择。

3.如果您需要一个反应式可变对象,并且希望跟踪该对象的深度变异属性,那么使用reactive()是一个不错的选择。

7.总结

这篇文章介绍了组合API中ref()和reactive()之间的差异:

1.ref()可以存储基元值,而reactive()不能。

2.您可以使用.value访问存储在ref()中的值,而reactive()对象可以直接用作常规对象。

3.ref()值可以重新分配给一个全新的对象,而reactive()不能。

4.ref()类型为ref<V>,而反应对象返回

Logo

腾讯云面向开发者汇聚海量精品云计算使用和开发经验,营造开放的云计算技术生态圈。

更多推荐