vue3.x教程-监视器watch和watchEffect区别对比 作者:马育民 • 2026-07-19 18:51 • 阅读:10000 # 介绍 1. **watch**:**显式指定依赖源**,主动告诉框架要监听谁,依赖需要手动罗列 2. **watchEffect**:**自动收集依赖**,函数内部用到哪些响应式变量,就自动监听哪些,无需手动传源 # 语法 ### watch ```ts 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 ```ts 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 ```ts watch(searchKey, (newVal, oldVal, onCleanup) => { const timer = setTimeout(() => { /* 请求 */ }, 500) onCleanup(() => clearTimeout(timer)) }) ``` #### watchEffect ```ts watchEffect((onCleanup) => { const timer = setTimeout(() => {}, 500) onCleanup(() => clearTimeout(timer)) }) ``` # 适用场景 ### 什么时候用 watch 1. 需要**新旧值对比**做逻辑(比如判断数值增减) 2. 只监听**某一个/少数几个**变量,希望其他变量变化不触发回调(精准控制) 3. 不需要初始化执行,只在数据修改后触发(不配置immediate) 4. 监听 props、路由、单独状态,逻辑和指定数据源强绑定 ### 什么时候用 watchEffect 1. 依赖多、不想手动罗列一堆监听源,简化代码 2. 逻辑依赖多个响应式变量,任意一个变化都要重新执行 3. 初始化就需要执行一次逻辑(接口请求、初始化计算) 4. 不需要旧值,只需要基于最新状态执行操作 # 总结 - **watch:手动指定依赖,有新旧值,默认不初始化,适合精准监听单一数据** - **watchEffect:自动收集依赖,无旧值,初始化自动执行,适合多依赖聚合逻辑** 原文出处:http://malaoshi.top/show_1GW3hpGfQxfH.html