Skip to content

VueJS - Watch 属性

在 Vue 中,侦听器(watchers)允许您响应响应式(reactive)数据的变化来执行操作。本章节将演示如何在 Vue 3 中使用侦听器,包括经典的选项式 API(Options API)和现代的组合式 API(Composition API)。

当特定的数据发生变化时,侦听器对于执行异步操作或复杂的逻辑非常有用。

想象一下,您有两个输入字段,一个用于输入千米,一个用于输入米。当其中一个字段的值发生变化时,您希望另一个字段根据转换(1千米 = 1000米)自动更新。侦听器非常适合这种场景。

组合式 API 提供了 watch 函数来创建侦听器。这是推荐用于新的 Vue 3 应用的方法。

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Vue 3 Watchers (Composition API)</title>
<script src="https://unpkg.com/vue@3"></script>
</head>
<body>
<div id="app">
<h2>Kilometer / Meter Converter (Composition API)</h2>
<label>Kilometers:</label>
<input type="number" v-model="kilometers" />
<br/>
<label>Meters:</label>
<input type="number" v-model="meters" />
</div>
<script>
const { createApp, ref, watch } = Vue;
const app = createApp({
setup() {
const kilometers = ref(0);
const meters = ref(0);
// Watch for changes in kilometers
// 侦听 kilometers 的变化
watch(kilometers, (newKilometers) => {
// Avoid infinite loops by checking if the value is already correct
// 通过检查值是否已经正确来避免无限循环
if (newKilometers * 1000 !== meters.value) {
meters.value = newKilometers * 1000;
}
});
// Watch for changes in meters
// 侦听 meters 的变化
watch(meters, (newMeters) => {
if (newMeters / 1000 !== kilometers.value) {
kilometers.value = newMeters / 1000;
}
});
return {
kilometers,
meters
};
}
});
app.mount('#app');
</script>
</body>
</html>

在这个组合式 API 示例中:

  • 我们从 Vue 中导入了 createApp、ref 和 watch。
  • 我们使用 ref(0) 将 kilometers 和 meters 定义为响应式引用(reactive references)。
  • 我们使用了 watch 函数。第一个参数是要侦听的响应式源(例如 kilometers)。第二个参数是一个回调函数(callback function),当源发生变化时运行。回调函数接收新值(newKilometers),并且可以选择接收旧值。
  • 在侦听器回调函数内部,我们更新了另一个响应式变量(例如,当 kilometers 改变时更新 meters)。
  • 我们在侦听器内部添加了检查 (if (newKilometers * 1000 !== meters.value)),以防止可能发生的无限更新循环。这种循环可能在设置一个值时立即触发另一个侦听器,而该侦听器又将第一个值设置回去时发生。

使用选项式 API (watch 选项) 的示例

Section titled “使用选项式 API (watch 选项) 的示例”

选项式 API 的方法是在组件的 watch 选项中定义侦听器。

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Vue 3 Watchers (Options API)</title>
<script src="https://unpkg.com/vue@3"></script>
</head>
<body>
<div id="app-options">
<h2>Kilometer / Meter Converter (Options API)</h2>
<label>Kilometers:</label>
<input type="number" v-model="kilometers" />
<br/>
<label>Meters:</label>
<input type="number" v-model="meters" />
</div>
<script>
const { createApp } = Vue;
const appOptions = createApp({
data() {
return {
kilometers: 0,
meters: 0
};
},
watch: {
// Watcher for the 'kilometers' data property
// meters 数据属性的侦听器
kilometers(newValue) {
// Avoid infinite loops
// 避免无限循环
if (newValue * 1000 !== this.meters) {
this.meters = newValue * 1000;
}
},
// Watcher for the 'meters' data property
// meters 数据属性的侦听器
meters(newValue) {
if (newValue / 1000 !== this.kilometers) {
this.kilometers = newValue / 1000;
}
}
},
// Computed properties are often a better fit for simple dependencies
// 对于简单的依赖关系,计算属性通常更适合
// See the chapter on Computed Properties for comparison.
// 请参阅计算属性的章节进行比较。
computed: {
// Example showing computed equivalent (might be simpler here)
// 显示等效计算属性的示例(在此处可能更简单)
/*
metersFromKm: {
get() { return this.kilometers * 1000; },
set(val) { this.kilometers = val / 1000; }
}
*/
}
});
appOptions.mount('#app-options');
</script>
</body>
</html>

在这个选项式 API 示例中:

  • kilometers 和 meters 在 data 选项中定义。
  • watch 选项包含以其侦听的数据属性命名的函数(例如 kilometers(newValue))。
  • 侦听器方法内部的逻辑与组合式 API 示例类似,使用 this 访问其他数据属性。
  • 其中包含了一个被注释掉的 computed 属性示例。对于像这种单位转换之类的简单同步依赖关系,计算属性通常比侦听器更简洁,性能也更好。
  • 当某个值(如 ID)改变时异步获取数据。
  • 执行不直接映射到计算值的复杂逻辑或副作用。
  • 基于数据的快速变化进行节流(throttling)或防抖(debouncing)操作(通常结合 Lodash 等工具库)。
  • 响应状态变化与浏览器 API 或第三方库交互。

在实现 watch 之前,请记住考虑 computed 属性是否可能是更简单、更合适的解决方案。

有关更多详细信息,请参阅 Vue 3 官方文档关于侦听器的内容。