在 Vue 3 中,ref 和 reactive 是两种用于创建响应式数据的 API。它们都可以使数据具有响应性,但在使用场景和实现方式上有一些区别。以下是 ref 和 reactive 的主要区别:
1. 数据类型
ref:通常用于基本数据类型(如 number、string、boolean 等),但也可以用于对象和数组。ref 会将数据包装在一个对象中,并通过 .value 属性来访问和修改数据。
import { ref } from 'vue';
const count = ref(0); // 基本数据类型
const user = ref({ name: 'Alice', age: 25 }); // 对象
console.log(count.value); // 0
console.log(user.value.name); // Alice
reactive:用于对象和数组等复杂数据类型。reactive 会直接返回一个响应式代理对象,不需要通过 .value 来访问数据。
import { reactive } from 'vue';
const state = reactive({
count: 0,
user: { name: 'Alice', age: 25 },
});
console.log(state.count); // 0
console.log(state.user.name); // Alice
2. 访问和修改数据
ref:需要通过 .value 属性来访问和修改数据。这是因为 ref 将数据包装在一个对象中,以确保基本数据类型也具有响应性。
const count = ref(0);
console.log(count.value); // 0
count.value ; // 修改数据
console.log(count.value); // 1
reactive:直接访问和修改对象的属性,不需要 .value。
const state = reactive({ count: 0 });
console.log(state.count); // 0
state.count ; // 修改数据
console.log(state.count); // 1
3. 使用场景
ref:适合用于基本数据类型,或者在需要将某个值单独提取出来作为响应式数据时使用。由于 ref 需要通过 .value 访问数据,因此在模板中使用时可能会稍显繁琐。
const count = ref(0);
// 在模板中使用
// <div>{{ count }}</div> <!-- 错误 -->
// <div>{{ count.value }}</div> <!-- 正确 -->
reactive:适合用于对象和数组等复杂数据结构。reactive 可以直接在模板中使用,不需要 .value。
const state = reactive({ count: 0 });
// 在模板中使用
// <div>{{ state.count }}</div> <!-- 正确 -->
4. 解构和响应性
ref:解构 ref 时,响应性不会丢失,因为每个 ref 都是独立的响应式对象。
const count = ref(0);
const { value } = count; // 解构
console.log(value); // 0
reactive:解构 reactive 对象时,响应性会丢失。因为解构后的变量是普通变量,不再具有响应性。
const state = reactive({ count: 0 });
const { count } = state; // 解构
console.log(count); // 0
count ; // 不会触发视图更新
如果需要解构 reactive 对象并保持响应性,可以使用 toRefs:
import { reactive, toRefs } from 'vue';
const state = reactive({ count: 0 });
const { count } = toRefs(state); // 使用 toRefs 解构
console.log(count.value); // 0
count.value ; // 会触发视图更新
5. 性能
ref:由于 ref 将数据包装在一个对象中,因此在处理大量基本数据类型时,可能会有轻微的性能开销。
reactive:reactive 直接代理整个对象,因此在处理复杂数据结构时,性能表现更好。
总结
ref:适合用于基本数据类型,或者在需要将某个值单独提取出来作为响应式数据时使用。需要通过 .value 访问和修改数据。
reactive:适合用于对象和数组等复杂数据结构。直接访问和修改对象的属性,不需要 .value。
在实际开发中,你可以根据具体需求选择使用 ref 或 reactive,或者两者结合使用。例如,可以在 reactive 对象中使用 ref 来处理基本数据类型:
import { reactive, ref } from 'vue';
const state = reactive({
count: ref(0),
user: { name: 'Alice', age: 25 },
});
console.log(state.count.value); // 0
state.count.value ; // 修改数据
这样可以充分利用两者的优势,使代码更加灵活和高效。