在 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 ; // 修改数据
这样可以充分利用两者的优势,使代码更加灵活和高效。