vue3 中 ref 和 reactive 有什么区别?
参考答案:
在 Vue 3 中,ref 和 reactive 都是用于创建响应式数据的核心 API,但它们在用途、返回值、适用场景和底层机制上存在明显差异。理解这两者的区别,有助于合理选择响应式策略、避免不必要的副作用,也有助于提升开发效率与代码一致性。
一、基本用途与语法对比
ref
- 用于 包裹一个基本类型或对象,返回一个响应式对象,其值通过
.value访问。 - 适合处理单个值或希望显式管理响应式引用的场景。
ts
import { ref } from 'vue';
const count = ref(0);
count.value++; // 必须通过 .value 访问reactive
- 用于 将整个对象转换为响应式对象,直接访问属性即可触发响应式更新。
- 更适合处理结构化的数据(对象、数组、嵌套结构等)。
ts
import { reactive } from 'vue';
const state = reactive({ count: 0 });
state.count++; // 直接访问属性即可二、响应式行为差异
1. 响应式深度
ref:对基本类型做响应式包裹;对对象是浅层包裹,内部对象不会自动递归为响应式。tsconst obj = ref({ a: 1 }); obj.value.a = 2; // a 是响应式的,因为 Vue 内部自动转为 reactivereactive:会将对象的所有嵌套属性递归转换为响应式(深层响应式)。tsconst obj = reactive({ a: { b: 1 } }); obj.a.b = 2; // b 是响应式的
2. 访问方式
ref:需要.value访问包裹的内容;reactive:可直接访问属性。
不过在模板中(<template>),Vue 会自动解包 ref,所以不需要加 .value。
三、在对象解构时的行为
ref会失去响应性:tsconst count = ref(0); const { value } = count; // value 是普通值,响应性丢失reactive直接解构会丢失响应性,推荐使用toRefs保留响应性:tsconst state = reactive({ count: 0 }); const { count } = toRefs(state); // count 变为 ref
四、典型使用场景对比
| 场景 | 使用建议 | 原因或说明 |
|---|---|---|
| 基本类型的响应式值(数值、布尔等) | 使用 ref | 轻量、语义清晰 |
| 对象、数组、结构化数据 | 使用 reactive | 自动深层响应式,写法简洁 |
| 对象属性需要解构出来使用 | 配合 toRefs | 避免响应性丢失 |
| 在组合式 API 中管理局部状态 | 两者都可 | 视具体数据结构选择 |
| 定义类或工厂中需显式包装状态 | 使用 ref | 更适合封装为单个引用 |
五、底层实现差异
ref是对值的响应式容器封装,内部通过Object.defineProperty定义.value,并调用reactive对对象自动包裹;reactive则是直接对目标对象进行 Proxy 包裹,返回一个代理对象,重写get/set等操作符;- 两者都基于 Vue 3 的响应式系统(
effect,track,trigger),但入口形式和封装语义不同。
题目要点:
ref更适合基本类型或希望明确响应式边界的场景,需要通过.value访问;reactive适用于复杂对象,具备深层响应式能力;- 解构响应式对象时注意响应性丢失问题,推荐配合
toRefs使用; - 模板中 Vue 会自动解包
ref,但在 JS 中仍需显式.value; - 理解两者底层差异有助于组合式 API 的灵活使用和封装。