vue3中watch的用法以及使用场景以及与watchEffect的使用对比

在 Vue 3 中,watchwatchEffect 是响应式系统的重要工具,帮助开发者监听数据变化并执行副作用操作。为了让你更好地理解 watchwatchEffect 的用法及其区别,这里将详细解释它们的使用方式、适用场景以及它们在基本类型和引用类型上的监听效果。


1. watch 的用法和适用场景

watch 用于监听特定的响应式数据或计算属性变化,并执行相应的回调。适合用于处理数据变化后的副作用,例如 API 请求、数据验证等。

基本用法

watch 需要传入两个主要参数:

  1. 监听目标:可以是 refreactive 数据,或是一个返回响应式数据的函数。
  2. 回调函数:在数据变化时触发,接收两个参数 newValueoldValue,分别表示新值和旧值。
import { ref, watch } from 'vue';

const count = ref(0);

watch(count, (newValue, oldValue) => {
  console.log(`count changed from ${oldValue} to ${newValue}`);
});

count.value = 5; // 输出:count changed from 0 to 5
使用场景
  • 监听数据并执行副作用:适合处理需要监听数据变化的场景,例如在用户输入时进行数据验证或 API 调用。

2. watch 监听 ref 定义的基本类型

ref 定义的基本类型数据如 numberstring 等,在数据变化时可以直接触发 watch 回调。

const message = ref('Hello');

watch(message, (newMessage, oldMessage) => {
  console.log(`Message changed from "${oldMessage}" to "${newMessage}"`);
});

message.value = 'Hello Vue 3!'; // 输出:Message changed from "Hello" to "Hello Vue 3!"

3. watch 监听 ref 定义的引用类型

ref 定义的引用类型数据(对象、数组)在监听时有两种情况:

  • 监听整体引用:修改整个对象时会触发回调并返回新旧值。
  • 监听内部属性:直接修改对象的属性不会触发回调,除非使用 { deep: true } 深度监听。
const user = ref({ name: 'Alice', age: 25 });

watch(user, (newUser, oldUser) => {
  console.log(`User changed from`, oldUser, `to`, newUser);
}, { deep: true });

// 修改整个对象会触发回调
user.value = { name: 'Bob', age: 30 }; // 输出:User changed from {name: 'Alice', age: 25} to {name: 'Bob', age: 30}

// 修改属性时也会触发回调,因为深度监听了
user.value.age = 26; // 输出:User changed from {name: 'Bob', age: 25} to {name: 'Bob', age: 26}

4. watch 监听 reactive 对象

reactive 适用于创建深层响应式对象,例如嵌套对象或复杂结构。通过 watch 可以监听整个对象,也可以监听对象的某个属性变化。

监听整个 reactive 对象

设置 { deep: true } 可以递归监听 reactive 对象中的每一个属性,确保任何内部属性变化都能触发回调。

import { reactive, watch } from 'vue';

const user = reactive({ name: 'Alice', age: 25, address: { city: 'NY', zip: '10001' } });

watch(user, (newUser, oldUser) => {
  console.log(`User changed from`, oldUser, `to`, newUser);
}, { deep: true });

// 修改嵌套属性
user.address.city = 'LA'; // 输出:User changed from {name: 'Alice', age: 25, address: {city: 'NY', zip: '10001'}} to {name: 'Alice', age: 25, address: {city: 'LA', zip: '10001'}}
监听 reactive 对象的单个属性

使用函数来监听特定属性的变化,避免递归监听整个对象,提升性能。

watch(() => user.age, (newAge, oldAge) => {
  console.log(`Age changed from ${oldAge} to ${newAge}`);
});

user.age = 27; // 输出:Age changed from 25 to 27

5. 监听多个数据

watch 可以同时监听多个数据,传入一个包含多个目标的数组即可。这种方法适合处理多个响应式数据的变化。

const firstName = ref('John');
const lastName = ref('Doe');

watch([firstName, lastName], ([newFirst, newLast], [oldFirst, oldLast]) => {
  console.log(`Name changed from ${oldFirst} ${oldLast} to ${newFirst} ${newLast}`);
});

firstName.value = 'Jane'; // 输出:Name changed from John Doe to Jane Doe
lastName.value = 'Smith'; // 输出:Name changed from Jane Doe to Jane Smith

6. watchEffect 的用法

watchEffect 是 Vue 3 的一种自动依赖追踪方式,不需要手动指定依赖项。在回调函数中访问的所有响应式数据都会成为依赖,只要这些数据变化,回调函数会自动重新执行。

基本用法
import { ref, watchEffect } from 'vue';

const count = ref(1);
const doubled = ref(2);

watchEffect(() => {
  console.log(`Count is ${count.value}, Double is ${doubled.value}`);
});

count.value = 2; // 输出:Count is 2, Double is 2
doubled.value = 4; // 输出:Count is 2, Double is 4
适用场景

watchEffect 适合自动响应简单的数据变化,尤其是需要自动执行的逻辑,省去了手动指定依赖项的步骤。常用于在挂载时执行的逻辑,或者需要自动收集依赖的副作用处理。

const firstName = ref('John');
const lastName = ref('Doe');

watchEffect(() => {
  console.log(`Full name is ${firstName.value} ${lastName.value}`);
});

firstName.value = 'Jane'; // 输出:Full name is Jane Doe
lastName.value = 'Smith'; // 输出:Full name is Jane Smith

7. watch vs watchEffect 的对比

特性 watch watchEffect
手动指定依赖 需要手动指定 自动收集依赖
使用新旧值对比 可以获得新旧值,适合对比数据变化 不提供新旧值,适合自动响应数据变化
常用场景 适合监听特定数据,适用于精确控制数据变化时的副作用 适合快速响应简单数据变化,如在组件挂载后执行逻辑
深度监听 可以使用 { deep: true } 进行深度监听 无法深度监听
性能和灵活性 可精确控制依赖项更新,适合复杂逻辑 简单灵活,适合自动响应依赖项变化

总结

  • watch:适合用于处理数据变化的副作用,尤其是异步请求、数据对比、深度监听复杂对象等场景。可以获取新旧值,灵活控制副作用逻辑。
  • watchEffect:适合自动依赖收集的简单场景,如在组件挂载时立即执行,且依赖项会自动更新,不需要手动指定依赖项。

通过灵活运用 watchwatchEffect,可以让 Vue 3 应用的数据响应更加高效,提升代码的可读性和维护性。

上一篇:在使用new Date生成时间戳时,发现数据库中 的时间总是多出一秒钟。


下一篇:[RK3566-Android11] 使用SPI方式点LED灯带-JE2815/WS2812,实现呼吸/渐变/随音量变化等效果