浅谈vue3中ref和reactive的区别
在 Vue 3 中,ref 和 reactive 是 Composition API 中用于创建响应式数据的两个核心函数,它们的区别主要体现在以下几个方面:
1. 支持的数据类型
ref:
-
可以包装 任意类型的值,包括基本类型(number、string、boolean)和对象类型(Object、Array、Map、Set 等)。
-
对对象类型内部会调用 reactive 进行深层响应式转换。
const num = ref(0); // 基本类型
const obj = ref({ a: 1 }); // 对象类型
reactive:
- 仅支持 对象类型(包括对象、数组、集合等)。直接用于基本类型会抛出警告。
const state = reactive({ count: 0 }); // 对象类型
// const num = reactive(0); // 错误!
2. 访问和修改方式
ref:
- 通过 .value 访问或修改值(模板中自动解包,无需 .value)。
const count = ref(0);
console.log(count.value); // 读取
count.value = 1; // 修改
reactive:
- 直接访问或修改属性,无需 .value。
const state = reactive({ count: 0 });
console.log(state.count); // 读取
state.count = 1; // 修改
3. 响应式实现原理
ref:
-
对基本类型使用 Object.defineProperty 的 getter/setter 实现响应式。
-
对对象类型内部调用 reactive,通过 Proxy 实现深层响应式。
reactive:
- 使用 Proxy 代理整个对象,递归处理嵌套属性,实现深层次响应式。
4. 替换对象的响应性
ref:
- 允许直接替换整个对象(通过 .value = newObject),新对象会自动转为响应式。
const obj = ref({ a: 1 });
obj.value = { b: 2 }; // 新对象仍为响应式
reactive:
- 直接替换整个对象会 失去响应性(因为响应式绑定的是原对象的引用)。
let state = reactive({ a: 1 });
state = reactive({ a: 2 }); // 错误!原 state 的响应式连接丢失
5. 解构和展开
ref:
- 解构时需要保留 .value 的引用,否则会失去响应性。
const count = ref(0);
const { value: countValue } = count; // 保持响应式需操作 .value
reactive:
- 直接解构或展开会丢失响应性,需用 toRefs 转为多个 ref。
const state = reactive({ a: 1, b: 2 });
const { a, b } = toRefs(state); // 转为 ref
6. 模板中的使用
ref:
- 在模板中自动解包,无需 .value(嵌套在对象中时也自动解包)。
reactive:
- 直接访问属性,保持响应式。
总结:使用场景
ref:
- 基本类型值。
- 需要替换整个对象的场景(如接口返回的数据替换)。
- 需要将值传递到函数或组件时(.value 显式操作更直观)。
reactive:
- 复杂的对象或嵌套数据,且不需要整体替换。
- 需要直接访问属性(避免 .value 的冗余写法)。