ref
不会递归地对 对象 或 数组 中的每个属性或元素进行深度响应式处理。如果你需要递归处理嵌套属性,reactive
是更适合的选择。让我通过具体的例子来展示这一点。
例子:ref
存储对象和嵌套对象
1. 使用 ref
存储嵌套对象:
import { createApp, ref } from 'vue';
createApp({
setup() {
// 使用 ref 存储对象,包含嵌套属性
const user = ref({
name: 'Alice',
profile: {
age: 25,
address: 'New York'
}
});
// 修改嵌套属性
function updateUser() {
user.value.profile.age = 26; // 修改嵌套对象的属性
}
return {
user, // 返回 user 对象给模板
updateUser
};
}
}).mount('#app');
模板部分:
<div id="app">
<p>Name: {{ user.value.name }}</p>
<p>Age: {{ user.value.profile.age }}</p>
<button @click="updateUser">Update Age</button>
</div>
问题:
在这个例子中,ref
用于存储一个 对象,对象内有一个嵌套的 profile
对象。user.value.profile.age
是嵌套属性,它应该是响应式的。但问题在于,ref
不会递归地对嵌套对象进行响应式处理。user.value.profile
并不是深度响应式的,而是浅响应式的。
这意味着,当你修改 user.value.profile.age
时,Vue 不会自动更新视图,因为 profile
对象没有被 深度响应式化。
解决方法:
如果我们希望 profile
对象的嵌套属性(如 age
和 address
)也能触发视图更新,我们需要通过 reactive
来深度响应式化这个对象。
2. 使用 reactive
存储嵌套对象:
import { createApp, reactive } from 'vue';
createApp({
setup() {
// 使用 reactive 创建深度响应式对象
const user = reactive({
name: 'Alice',
profile: {
age: 25,
address: 'New York'
}
});
// 修改嵌套属性
function updateUser() {
user.profile.age = 26; // 修改嵌套对象的属性
}
return {
user, // 返回 user 对象给模板
updateUser
};
}
}).mount('#app');
模板部分:
<div id="app">
<p>Name: {{ user.name }}</p>
<p>Age: {{ user.profile.age }}</p>
<button @click="updateUser">Update Age</button>
</div>
解释:
- 在这个例子中,
reactive
用来将user
对象及其内部属性(如profile
)深度响应式化。 - 现在,修改
user.profile.age
时,profile
对象 和age
属性 都是 深度响应式的,因此视图会自动更新。
总结:
ref
存储 对象 或 数组 时,它只会 创建响应式引用,不会递归地对对象的嵌套属性进行响应式处理。你需要使用.value
来访问和修改对象的内容。如果对象有嵌套的属性,ref
无法保证它们是响应式的,除非显式地使用reactive
。reactive
会对 对象 及其所有 嵌套属性 进行深度响应式处理,无需使用.value
,并且修改嵌套属性时视图会自动更新。
何时使用 ref
和 reactive
?
ref
适用于 基本数据类型(如number
、string
)以及 简单的对象或数组,但你需要通过.value
来访问和修改数据。reactive
适用于 复杂数据类型(如 对象 或 数组),并且会自动递归地将对象的每个属性都变成响应式。