
ref及reactive的区别及本质
ref()是使用.value属性访问和更新的,而reactive()是原始对象的代理。ref返回的ref(值:T)的类型为ref,而reactive返回的reactive对象(对象:T)为T类型(异常:reactive中的ref被展开)。ref()数据使用value属性访问(异常:在模板中,ref是自动展开的),而reactive()数据则直接访问。尽管如此,用对象初始化的reactive({co
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>,而反应对象返回
更多推荐
所有评论(0)