在 Vue 3 中,watch
和 watchEffect
都是用于观察响应式数据变化并执行副作用的 API,但它们在用法和设计目的上有明显区别:
**watch
**
需要显式指定监听的数据源(通过第一个参数传入),可以是响应式对象、ref 或计算属性。
示例:
javascript复制watch(count, (newVal, oldVal) => { /* ... */ })
或监听多个数据源:
javascript复制watch([count, name], ([newCount, newName], [oldCount, oldName]) => { /* ... */ })
**watchEffect
**
自动收集依赖:在回调函数中用到的响应式数据会被自动追踪。无需手动声明依赖。
示例:
javascript复制watchEffect(() => { console.log(count.value + name.value); // 自动追踪 count 和 name});
**watch
**
默认惰性执行:首次创建时不会立即运行回调,除非设置 immediate: true
。
示例:
javascript复制watch(count, callback, { immediate: true }); // 立即执行一次
**watchEffect
**
立即执行:创建时会立即运行一次回调,用于收集依赖。适合需要初始化的副作用。
**watch
**
提供变化前后的值(newValue
和 oldValue
):
javascript复制watch(count, (newVal, oldVal) => { /* ... */ });
**watchEffect
**
没有新旧值参数:回调函数中直接访问当前值,适用于不需要旧值的场景。
javascript复制watchEffect(() => { console.log(count.value); // 只获取当前值});
**watch
**
需要精确控制监听的数据源。
需要获取旧值或比较新旧值。
需要惰性执行(如仅在数据变化时触发)。
**watchEffect
**
依赖多个数据源,且逻辑简单(自动收集依赖)。
需要立即执行副作用(如初始化请求)。
逻辑与依赖关系高度耦合,无需手动维护依赖列表。
两者都返回一个 **stop
函数**,调用即可停止监听:
javascript复制const stopWatch = watch(/* ... */);const stopEffect = watchEffect(/* ... */);stopWatch(); // 停止 watchstopEffect(); // 停止 watchEffect
特性 | watch | watchEffect |
---|---|---|
依赖声明 | 显式指定 | 自动收集 |
首次执行 | 默认惰性(需 immediate: true ) | 立即执行 |
新旧值 | 提供 | 不提供 |
多数据源监听 | 支持数组形式 | 自动收集多个依赖 |
适用场景 | 精确控制依赖、需要旧值 | 简单副作用、依赖自动追踪 |
根据需求选择:需要细粒度控制时用 watch
,简化代码逻辑时用 watchEffect
。