目录
Vue 3 响应式 API:watch
、watchEffect
、watchPostEffect
和 watchSyncEffect
Vue 3 引入了一系列新的响应式 API,使开发者能够更灵活地处理数据变化。这些 API 包括 watch
、watchEffect
、watchPostEffect
和 watchSyncEffect
。在这篇文章中,我们将详细介绍每一个 API,并探讨它们的使用场景和差异。
1. watch
watch
是 Vue 2 中就有的 API,Vue 3 中对其进行了增强。它主要用于观察响应式数据的变化,并在数据变化时执行特定的回调函数。
使用示例
import { ref, watch } from 'vue';
const count = ref(0);
watch(count, (newVal, oldVal) => {
console.log(`count changed from ${oldVal} to ${newVal}`);
});
// 修改 count 的值
count.value++;
在这个示例中,当 count 的值变化时,回调函数会被触发,打印出旧值和新值。
应用产场景
- 需要对特定响应式数据的变化做出反应。
- 执行异步操作(如数据获取)时。
详细信息
第一个参数是侦听器的源
- 一个函数,返回一个值
- 一个ref
- 一个响应式对象
- …或则是以上类型组成的数组
第二个参数是在发生变化时要调用的回调函数。这个回调函数接受三个参数:新值、旧值,以及一个用于注册副作用清理的回调函数。该回调函数会在副作用下一次重新执行前调用,可以用来清除无效的副作用,例如等待中的异步请求。
当侦听多个来源时,回调函数接受两个数组,分别对应来源数组中的新值和旧值。
第三个可选参数是一个对象,支持以下选项:
- immediate:在侦听器创建时立即触发回调。第一次调用时旧值是 undefined。
- deep:如果源是对象,强制深度遍历,以便在深层级变更时触发回调。参考深层侦听器。
- flush:调整回调函数的刷新时机。参考回调的刷新时机及 watchEffect()。
- onTrack / onTrigger:调试侦听器的依赖。
- once:回调函数只会运行一次。侦听器将在回调函数首次运行后自动停止。
与 watchEffect() 相比,watch() 使我们可以:
- 懒执行副作用;
- 更加明确是应该由哪个状态触发侦听器重新执行;
- 可以访问所侦听状态的前一个值和当前值。
2. watchEffect
watchEffect
是 Vue 3 中的新 API,它用于自动收集依赖,并在任何依赖变化时重新运行回调函数。与 watch 不同,watchEffect 是立即执行的,并且不需要显式地指定依赖。
使用示例
import { ref, watchEffect } from 'vue';
const count = ref(0);
const doubled = ref(0);
watchEffect(() => {
doubled.value = count.value * 2;
console.log(`doubled is now ${doubled.value}`);
});
// 修改 count 的值
count.value++;
在这个示例中,当 count
的值变化时,watchEffect
会自动重新运行,并更新 doubled
的值。
应用产场景
- 需要自动追踪多个响应式数据。需要在响应式数据变化后执行 DOM 操作。
- 简化响应式逻辑,不需要显式地声明依赖。
详细信息
第一个参数就是要运行的副作用函数。这个副作用函数的参数也是一个函数,用来注册清理回调。清理回调会在该副作用下一次执行前被调用,可以用来清理无效的副作用,例如等待中的异步请求 (参见下面的示例)。
第二个参数是一个可选的选项,可以用来调整副作用的刷新时机或调试副作用的依赖。
默认情况下,侦听器将在组件渲染之前执行。设置 flush: 'post'
将会使侦听器延迟到组件渲染之后再执行。详见回调的触发时机。在某些特殊情况下 (例如要使缓存失效),可能有必要在响应式依赖发生改变时立即触发侦听器。这可以通过设置 flush: 'sync'
来实现。然而,该设置应谨慎使用,因为如果有多个属性同时更新,这将导致一些性能和数据一致性的问题。
返回值是一个用来停止该副作用的函数。
3. watchPostEffect
watchPostEffect
是一种特定类型的 watchEffect 即 flush: 'post'
,它在所有 DOM 更新完成之后运行。这对于在响应式数据变化后需要进行 DOM 操作的情况非常有用。
使用示例
import { ref, watchPostEffect } from 'vue';
const count = ref(0);
watchPostEffect(() => {
console.log(`DOM updated with count: ${count.value}`);
});
// 修改 count 的值
count.value++;
在这个示例中,当 count
的值变化并且 DOM 更新完成后,watchPostEffect
会被触发,打印出最新的 count
值。
应用产场景
- 需要在响应式数据变化后执行 DOM 操作。
- 确保在 DOM 更新完成后执行的逻辑。
4. watchSyncEffect
watchSyncEffect
是另一种特定类型的 watchEffect
即 flush: 'sync'
,它在同步地触发更新,并且在 DOM 更新之前执行。这对于需要在 DOM 更新之前进行一些同步操作的情况非常有用。
使用示例
import { ref, watchSyncEffect } from 'vue';
const count = ref(0);
watchSyncEffect(() => {
console.log(`count is now ${count.value}`);
});
// 修改 count 的值
count.value++;
在这个示例中,当 count
的值变化时,watchSyncEffect
会立即同步触发并打印出最新的 count
值。
应用产场景
- 需要在 DOM 更新之前进行同步操作。
- 确保在 DOM 更新之前执行的逻辑。
总结
在 Vue 3 中,watch
、watchEffect
、watchPostEffect
和 watchSyncEffect
提供了更强大的工具来处理响应式数据的变化。每个 API 都有其独特的应用场景,可以根据具体需求选择合适的工具来实现更简洁、高效的代码。
希望这篇文章能帮助你更好地理解和使用 Vue 3 的响应式 API。Happy coding!