vue3.x教程-监视器watch和watchEffect区别对比

介绍

  1. watch:显式指定依赖源,主动告诉框架要监听谁,依赖需要手动罗列

  2. watchEffect:自动收集依赖,函数内部用到哪些响应式变量,就自动监听哪些,无需手动传源

语法

watch

import { ref, watch } from 'vue'
const count = ref(0)
// 第一个参数:监听源(单个/数组/函数)
watch(count, (newVal, oldVal) => {
  console.log('count变了', newVal, oldVal)
}, { deep: true, immediate: true })
  • 监听源支持:ref、reactive、getter函数、多个源数组
  • 回调参数自带 新值、旧值

watchEffect

import { ref, watchEffect } from 'vue'
const count = ref(0)
const name = ref('张三')
watchEffect(() => {
  // 内部用到count、name,自动收集为依赖
  console.log(count.value, name.value)
})
  • 无需传入监听源,函数内访问的响应式数据自动成为依赖
  • 回调没有旧值,只能拿到最新值

差异

对比维度 watch watchEffect
依赖收集 手动声明监听源 自动收集函数内所有响应式依赖
回调参数 (新值, 旧值) 仅能获取最新值,无oldVal
初始执行 默认不执行,需配置 immediate: true 才初始化触发 默认初始化立刻执行一次
深度监听 监听对象/数组需手动加 deep: true 自动深层监听内部属性,无需deep
多数据监听 传入数组 watch([a,b], cb) 函数内直接同时使用a、b即可,自动监听
精准控制 可精准指定只监听某一个变量,无关数据变化不触发 只要函数内任意依赖变动都会触发,粒度更粗
停止监听 返回停止函数 const stop = watch(...) stop() 返回停止函数 const stop = watchEffect(...) stop()
清除副作用 回调第三个参数 onCleanup 回调参数直接接收 onCleanup

副作用清除示例

watch

watch(searchKey, (newVal, oldVal, onCleanup) => {
  const timer = setTimeout(() => { /* 请求 */ }, 500)
  onCleanup(() => clearTimeout(timer))
})

watchEffect

watchEffect((onCleanup) => {
  const timer = setTimeout(() => {}, 500)
  onCleanup(() => clearTimeout(timer))
})

适用场景

什么时候用 watch

  1. 需要新旧值对比做逻辑(比如判断数值增减)
  2. 只监听某一个/少数几个变量,希望其他变量变化不触发回调(精准控制)
  3. 不需要初始化执行,只在数据修改后触发(不配置immediate)
  4. 监听 props、路由、单独状态,逻辑和指定数据源强绑定

什么时候用 watchEffect

  1. 依赖多、不想手动罗列一堆监听源,简化代码
  2. 逻辑依赖多个响应式变量,任意一个变化都要重新执行
  3. 初始化就需要执行一次逻辑(接口请求、初始化计算)
  4. 不需要旧值,只需要基于最新状态执行操作

总结

  • watch:手动指定依赖,有新旧值,默认不初始化,适合精准监听单一数据
  • watchEffect:自动收集依赖,无旧值,初始化自动执行,适合多依赖聚合逻辑

原文出处:/show_1GW3hpGfQxfH.html