Vue 3 监听属性 (Watchers)
在 Vue 3 中,侦听器(Watchers) 用于观察一个或多个响应式数据的变化,并在数据变化时执行一些异步或开销较大的操作。它是 Vue 提供的一种机制,可以让你在数据变化时做出反应,通常用于处理副作用或执行异步操作。
与计算属性(computed
)不同,计算属性 是依赖于响应式数据的计算值,只有在依赖的数据发生变化时才会重新计算。而 侦听器 允许你在数据变化时触发更复杂的逻辑,通常用于执行副作用操作,如发送 HTTP 请求、处理表单数据或操作外部库等。
1. 使用 watch
监听数据
你可以使用 watch
API 来监听响应式数据的变化。Vue 3 中的 watch
可以用于监听单个数据源,也可以监听多个数据源。
1.1. 监听单个属性
<template>
<div>
<p>Price: {{ price }}</p>
<button @click="price += 10">Increase Price</button>
</div>
</template>
<script>
import { ref, watch } from 'vue';
export default {
setup() {
const price = ref(100);
// 监听 price 变化
watch(price, (newValue, oldValue) => {
console.log(`Price changed from ${oldValue} to ${newValue}`);
});
return {
price
};
}
};
</script>
在这个例子中,我们使用 watch
监听 price
变量的变化。每当 price
发生变化时,都会触发回调函数,并打印出新的和旧的 price
值。
1.2. 监听多个属性
你也可以监听多个数据源(响应式属性)。你只需要将它们放在一个数组中:
<template>
<div>
<p>Price: {{ price }}</p>
<p>Quantity: {{ quantity }}</p>
<button @click="price += 10">Increase Price</button>
<button @click="quantity += 1">Increase Quantity</button>
</div>
</template>
<script>
import { ref, watch } from 'vue';
export default {
setup() {
const price = ref(100);
const quantity = ref(1);
// 监听 price 和 quantity
watch([price, quantity], ([newPrice, newQuantity], [oldPrice, oldQuantity]) => {
console.log(`Price changed from ${oldPrice} to ${newPrice}`);
console.log(`Quantity changed from ${oldQuantity} to ${newQuantity}`);
});
return {
price,
quantity
};
}
};
</script>
在这个例子中,当 price
或 quantity
发生变化时,侦听器会同时触发,输出变化的内容。
2. watch
的参数
- 第一个参数:需要监听的响应式数据,可以是单个数据源,也可以是一个数组,表示多个数据源。
- 第二个参数:当监听的响应式数据发生变化时,会调用的回调函数。这个回调函数有两个参数:
newValue
和oldValue
,分别代表数据变化后的值和变化前的值。 - 第三个参数(可选):一个对象,允许你配置侦听器的行为。
3. watch
的配置项
你可以在 watch
中传递配置项来控制侦听器的行为。常见的配置项包括:
3.1. immediate
immediate
选项会使侦听器在创建时立即执行一次回调,而不是等待数据变化之后再执行。
<template>
<div>
<p>Price: {{ price }}</p>
<button @click="price += 10">Increase Price</button>
</div>
</template>
<script>
import { ref, watch } from 'vue';
export default {
setup() {
const price = ref(100);
// 在数据变化前,立即执行一次
watch(price, (newValue, oldValue) => {
console.log(`Price changed from ${oldValue} to ${newValue}`);
}, {
immediate: true
});
return {
price
};
}
};
</script>
immediate: true
表示当组件初始化时,侦听器会立即触发一次回调。
3.2. deep
deep
选项可以让侦听器递归地监听对象或数组内部的嵌套属性。如果数据是一个对象或数组,且你希望监听其内部属性的变化,可以使用 deep
。
<template>
<div>
<p>{{ user }}</p>
<button @click="user.name = 'John'">Change Name</button>
</div>
</template>
<script>
import { ref, watch } from 'vue';
export default {
setup() {
const user = ref({
name: 'Alice',
age: 30
});
// 监听 user 对象的深层变化
watch(user, (newValue, oldValue) => {
console.log('User changed:', newValue);
}, {
deep: true
});
return {
user
};
}
};
</script>
在这个例子中,deep: true
表示监听 user
对象的内部属性(如 name
和 age
)的变化,而不仅仅是监听 user
本身的变化。
3.3. flush
flush
选项控制回调函数的调用时机。它可以接受以下值:
'sync'
(默认值):在数据变化后,立即同步执行回调。'post'
:在下次 DOM 更新周期后执行回调。'pre'
:在 DOM 更新之前执行回调。
<template>
<div>
<p>{{ price }}</p>
<button @click="price += 10">Increase Price</button>
</div>
</template>
<script>
import { ref, watch } from 'vue';
export default {
setup() {
const price = ref(100);
// 在 DOM 更新后执行
watch(price, (newValue, oldValue) => {
console.log(`Price changed from ${oldValue} to ${newValue}`);
}, {
flush: 'post'
});
return {
price
};
}
};
</script>
在此示例中,flush: 'post'
使得回调在 DOM 更新完成后才执行。
4. 使用 watchEffect
除了 watch
,Vue 3 还提供了一个更简洁的 watchEffect
API,适用于在副作用函数中直接响应依赖。
<template>
<div>
<p>Price: {{ price }}</p>
<button @click="price += 10">Increase Price</button>
</div>
</template>
<script>
import { ref, watchEffect } from 'vue';
export default {
setup() {
const price = ref(100);
// 自动追踪所有被访问的响应式数据
watchEffect(() => {
console.log(`Price is: ${price.value}`);
});
return {
price
};
}
};
</script>
watchEffect
会自动追踪其内部使用的响应式数据,每次相关数据变化时都会重新执行回调函数。它更适合用于无需显式指定依赖的简单场景。
总结
watch
允许你监听一个或多个响应式数据的变化,并在数据变化时执行回调。- 你可以使用
immediate
选项立即执行回调,使用deep
选项监听对象或数组的深层变化。 watchEffect
是另一种更简洁的方式,它会自动追踪函数中使用的响应式数据。- 侦听器 适合用于执行副作用操作,如数据变化时发送 HTTP 请求、执行异步操作等。
通过使用 watch
和 watchEffect
,你可以更加灵活地处理响应式数据的变化,进行复杂的副作用处理。
发表回复