Vue 3 中 watch 可借助闭包特性配合 onCleanup、精准依赖 getter、动态启停及结果缓存来优化性能:防止竞态、减少冗余触发、避免内存泄漏、降低重复计算开销。

Vue 3 中 watch 本身不直接通过“闭包函数”来优化性能,但可以利用闭包特性配合 onCleanup 和手动控制执行时机,避免竞态、重复请求或无效更新,从而显著降低副作用带来的运行开销。
用 onCleanup 防止竞态覆盖
搜索框输入联想是典型场景:用户快速输入,多次触发 watch,若后一次请求比前一次先返回,旧结果会覆盖新结果。闭包可保存每次请求的唯一标识,结合 onCleanup 实现优雅取消:
- 每次 watch 触发时,生成一个局部变量(如
pendingId),并将其封闭在回调作用域中 - 在异步操作开始前调用
onCleanup,标记该次请求已失效 - 请求返回后,检查当前
pendingId是否仍为本次有效值,仅当匹配才更新状态
避免监听整个 reactive 对象
直接 watch(state, ...) 会因任意字段变化都触发回调,造成冗余执行。闭包可封装精准依赖逻辑:
- 用 getter 函数作为 source,把真正关心的字段提取出来,例如
() => ({ q: searchQuery.value, page: pagination.page }) - 该函数体形成闭包,自动捕获所需 ref,既明确依赖又避免深度遍历整个对象
- 相比
deep: true,这种方式只追踪显式列出的值,响应更轻量
按需创建和销毁 watch 实例
watch 返回停止函数,这个能力在闭包环境下特别实用:
立即学习“前端免费学习笔记(深入)”;
- 在条件分支中动态创建 watch,比如仅当模块激活时监听特定数据
- 将 stop 函数存入闭包变量,在组件卸载或状态切换时主动调用,防止内存泄漏和无效回调执行
- 多个 watch 可共用同一套清理逻辑,例如统一在
onBeforeUnmount中批量 stop
缓存计算结果减少重复工作
如果 watch 回调内有高成本计算(如格式化大量数据、树形结构遍历),可在闭包中缓存中间结果:
- 声明局部 const 变量存储上一次计算输出,与新输入比对后再决定是否重算
- 配合
watch的oldVal参数,只在必要字段变更时触发耗时逻辑 - 注意:不要缓存响应式对象本身,应缓存派生值或结构化快照



















