immediate 仅在初始化时多执行一次 handler,无额外依赖收集;deep 则递归遍历整个对象树建立依赖,显著增加响应式开销,二者组合时性能瓶颈主要来自 deep。

immediate 和 deep 是 watch 中两个独立但常被一起使用的配置,它们解决不同问题,也带来不同的性能影响。
immediate 的开销:一次性的执行成本
开启 immediate: true 仅在组件初始化时多执行一次 handler,不增加后续监听负担。它本质是「提前调用」,不会触发额外依赖收集或响应式追踪。
- 执行时机:Watcher 实例创建后立刻调用 get() 并运行回调,此时 oldVal 为 undefined
- 无递归、不遍历、不建立新依赖 —— 只是早一次函数调用
- 适合用于初始化校验、首屏数据拉取、默认状态同步等场景
deep 的开销:持续性的响应式膨胀
deep: true 会显著改变响应式系统的运作方式。它不是简单“多看一层”,而是对整个对象树做递归依赖收集。
- Vue 需遍历目标对象所有嵌套属性(包括数组索引、对象键),为每个可响应的子值建立 watcher 依赖
- 每次修改任意深层字段(如 user.profile.avatar.url),都会触发该 watch 的 handler,即使你只关心其中某个字段
- 若对象含大量属性或深层嵌套(如 API 返回的完整用户档案),初始化时的遍历和后续更新时的触发链都会拖慢性能
二者组合时的真实代价
同时设 immediate: true 和 deep: true,等于「首次执行 + 全量依赖建立」。性能瓶颈几乎完全来自 deep。
- immediate 带来的只是第一次 handler 调用;真正吃资源的是 deep 引发的响应式代理构建过程
- 常见误用:监听整个 form 表单对象却未过滤字段,导致输入任一字段都触发全量校验逻辑
- 优化方向:优先监听具体路径(如 'formData.email')替代整个对象,避免 deep
更轻量的替代方案
不是所有嵌套变化都需要 deep。多数场景有更精准、更低开销的方式:
- 用计算属性(computed)派生关注的字段,再监听该计算属性
- 在数据变更源头(如 input 事件、API 响应处理)中显式触发逻辑,而非被动监听
- 对 Vuex/Pinia 中的状态,用模块化 getter 或 select 模式缩小监听范围


















