尤雨溪说:为什么Vue3 中应该使用 Ref 而不是 Reactive?
Hello,大家好,我是 winty。
每次有同学学习到
vue3
的时候,总会问我:“
ref
和
reactive
我们应该用哪个呢?” 我告诉他:“我们应该使用
ref
,而不是
reactive
”。那么此时同学就会有疑惑:“为什么呢?
ref
还需要
.value
处理,
reactive
看起来会更加简单呢?”
嗯....每当这个时候,我都需要进行一次长篇大论来解释这个问题。不过以后应该不需要了,因为这篇文章将会把这个事情解释的非常清楚......
为什么推荐使用ref而不是reactive
reactive
在使用过程中存在一些局限性,如果不额外注意这些问题,可能会给开发带来一些不便。与此不同,
ref
更像是Vue2时代的
option API
中的
data
的替代品,可以存放任何数据类型,而
reactive
声明的数据类型则仅限于对象。
总体来说,非必要的情况下最好避免使用
reactive
。官方文档也强烈推荐使用
ref()
作为声明响应式状态的主要API。以下是详细原因:
-
局限性问题:
reactive本身存在一些局限性,可能会在开发过程中引发一些问题。这需要额外的注意力和处理,否则可能对开发造成麻烦。 -
数据类型限制:
reactive声明的数据类型仅限于对象,而ref则更加灵活,可以容纳任何数据类型。这使得ref更适合一般的响应式状态的声明。 -
官方推荐:
官方文档强烈建议使用
ref()作为声明响应式状态的首选。这是因为ref更简单、更直观,同时避免了reactive可能引发的一些问题。
总的来说:除非有特定的需求需要使用
reactive
,否则在大多数情况下更推荐使用
ref()
。
最懂Vue的人都这么说了:推荐ref!!!!!!
reactive
和
ref
对比
|
reactive |
ref |
|---|---|
|
❌ 只支持对象和数组(引用数据类型) |
✅ 支持基本数据类型 + 引用数据类型 |
|
✅ 在 <script> 和 <template> 中无差别使用 |
❌ 在 <script> 和 <template> 使用方式不同(在 <script> 中要使用 .value) |
|
❌ 重新分配一个新对象会丢失响应性 |
✅ 重新分配一个新对象不会失去响应 |
|
能直接访问属性 |
需要使用 .value 访问属性 |
|
❌ 将对象传入函数时,失去响应 |
✅ 传入函数时,不会失去响应 |
|
❌ 解构时会丢失响应性,需使用 toRefs |
❌ 解构对象时会丢失响应性,需使用 toRefs |
即:
-
ref用于将基本类型的数据和引用数据类型(对象)转换为响应式数据,通过.value访问和修改。 -
reactive用于将对象转换为响应式数据,可以直接访问和修改属性,适用于复杂的嵌套对象和数组。
01:
reactive
有限的值类型
reactive
只能声明引用数据类型(对象)
ref
既能声明基本数据类型,也能声明对象和数组
Vue 提供了
ref()
方法,允许我们创建可以使用
任何值类型
的响应式
ref
。
使用
ref
,你可以灵活地声明基本数据类型、对象或数组,而不受像
reactive
那样只能处理引用数据类型的限制。这为开发提供了更大的灵活性,尤其是在处理不同类型的数据时。
02:
reactive
使用不当会失去响应
使用
reactive
时,如果不当使用,可能导致响应性失效,带来一些困扰。这可能让开发者在愉快编码的同时,突然发现某些操作失去了响应性,不明所以。因此,建议在不了解
reactive
失去响应的情况下慎用,而更推荐使用
ref
。
1. 赋值给
reactive
一个整个对象或
reactive
对象
赋值一个普通对象
赋值一个
reactive
对象
在
nextTick
中给
state
赋值一个
reactive
的响应式对象,但是 DOM 并没有更新。
解决方法:
- 不要直接整个对象替换,一个个属性赋值
-
使用
Object.assign
-
使用
ref定义对象
2. 将
reactive
对象的属性赋值给变量(断开连接/深拷贝)
这种操作类似于深拷贝,不再共享同一内存地址,而是只是字面量的赋值,对该变量的赋值不会影响原来对象的属性值。
解决方案:
-
避免将
reactive对象的属性赋值给变量。
3. 直接
reactive
对象解构时
直接解构会失去响应。
解决方案:
使用
toRefs
解构,解构后的属性是
ref
的响应式变量。
建议:
ref
一把梭
推荐使用
ref
,总结原因如下:
reactive
有限的值类型:只能声明引用数据类型(对象/数组)。
reactive
在一些情况下会失去响应,这可能导致数据回显失去响应(数据改了,DOM 没更新)。
上面这个例子如果是使用
ref
进行声明,直接赋值即可,不需要将属性拆分一个个赋值。
使用
ref
替代
reactive
: