在 Vue 2 和 Vue 3 中,watch 和 watchEffect 都是用于监听数据变化并执行副作用的 API,但它们在用法、监听方式、依赖追踪 等方面有显著区别,且 watchEffect 是 Vue 3 新增的 API(Vue 2 中不存在)。
1. 基本区别与存在版本
- 
watch : Vue 2 和 Vue 3 中均存在,是更传统的监听方式,需要明确指定要监听的数据源。 
- 
watchEffect : 仅存在于 Vue 3 中,是一种更简洁的监听方式,无需明确指定监听源,会自动追踪依赖。 
2. 核心区别对比
| 特性 | watch(Vue 2/3) | watchEffect(仅 Vue 3) | 
|---|---|---|
| 监听目标 | 需明确指定监听的数据源(如 data、computed等) | 无需指定,自动追踪函数内部使用的响应式数据 | 
| 初始化执行 | 默认不执行,需通过 immediate: true配置才会初始执行 | 默认初始执行一次(收集依赖) | 
| 依赖追踪 | 仅监听指定的数据源,若数据源是对象,需配置 deep: true才会深度监听 | 自动追踪函数内所有响应式数据,包括对象深层属性 | 
| 回调参数 | 回调函数接收新值、旧值两个参数( (newVal, oldVal) => {}) | 回调函数无参数,仅执行副作用逻辑 | 
| 停止监听 | Vue 2 中通过 vm.$watch返回的函数停止;Vue 3 中通过watch返回的函数停止 | 通过返回的函数停止监听 | 
3. 用法示例
(1)watch 的用法(Vue 2 和 Vue 3 类似)
Vue 2 中:
            
            
              js
              
              
            
          
          export default {
  data() {
    return {
      count: 0,
      user: { name: "张三" },
    };
  },
  watch: {
    // 监听基本类型
    count(newVal, oldVal) {
      console.log(`count 从 ${oldVal} 变为 ${newVal}`);
    },
    // 监听对象属性(需用字符串路径)
    "user.name"(newVal, oldVal) {
      console.log(`用户名从 ${oldVal} 变为 ${newVal}`);
    },
    // 深度监听对象(监听所有属性变化)
    user: {
      handler(newVal) {
        console.log("user 对象发生变化", newVal);
      },
      deep: true, // 开启深度监听
      immediate: true, // 初始化时执行一次
    },
  },
};Vue 3 组合式 API 中:
            
            
              js
              
              
            
          
          import { ref, reactive, watch } from "vue";
export default {
  setup() {
    const count = ref(0);
    const user = reactive({ name: "张三" });
    // 监听 ref
    watch(count, (newVal, oldVal) => {
      console.log(`count 从 ${oldVal} 变为 ${newVal}`);
    });
    // 监听 reactive 对象的属性
    watch(
      () => user.name,
      (newVal, oldVal) => {
        console.log(`用户名从 ${oldVal} 变为 ${newVal}`);
      }
    );
    // 深度监听(Vue 3 中监听 reactive 对象默认深度监听)
    watch(
      user,
      (newVal) => {
        console.log("user 对象变化", newVal);
      },
      { immediate: true }
    );
  },
};(2)watchEffect 的用法(仅 Vue 3)
            
            
              js
              
              
            
          
          import { ref, reactive, watchEffect } from "vue";
export default {
  setup() {
    const count = ref(0);
    const user = reactive({ name: "张三", age: 20 });
    // 自动追踪函数内使用的响应式数据
    const stop = watchEffect(() => {
      // 用到了 count 和 user.name,这两个数据变化时会触发回调
      console.log(`count: ${count.value}, 用户名: ${user.name}`);
    });
    // 3秒后停止监听
    setTimeout(stop, 3000);
  },
};- 初始时会执行一次,打印初始值。
- 当 count或user.name变化时,会重新执行回调。
- user.age变化时不会触发,因为函数内未使用该属性(自动追踪依赖)。
4. 适用场景
- 
watch : 适合需要明确知道数据变化前后的值 、只监听特定数据源 或需要控制是否深度监听/初始执行的场景。例如:监听路由变化、根据旧值和新值做不同处理。 
- 
watchEffect : 适合依赖较多且不需要区分新旧值的场景,写法更简洁。例如:数据变化后同步更新 DOM、发送请求等副作用操作。 
总结
- watch更灵活,需手动指定监听源,可获取新旧值,适合精确控制的场景。
- watchEffect更简洁,自动追踪依赖,默认初始执行,适合副作用逻辑较简单的场景。
- 注意:watchEffect是 Vue 3 新增 API,Vue 2 中无法使用。