前置知识: Vue 3

computed缓存机制与watch执行时机

1 minAdvanced2026/6/14

Vue 3 computed缓存机制与watch执行时机详解。

1. computed 缓存机制

1.1 惰性求值

computed 只有在被读取时才会计算,且缓存结果:

const count = ref(0);
const doubled = computed(() => {
  console.log('computed 执行');
  return count.value * 2;
});

// 首次读取:执行计算
console.log(doubled.value); // computed 执行 → 0

// 再次读取:返回缓存
console.log(doubled.value); // 无日志 → 0(缓存)

// 依赖变化
count.value = 1;
// 此时不会重新计算!computed 是惰性的

// 再次读取:重新计算
console.log(doubled.value); // computed 执行 → 2

1.2 脏标记机制

Vue 3 使用脏标记(dirty flag)实现缓存:

初始状态: dirty = true
首次读取: 执行计算 → dirty = false → 缓存结果
依赖变化: dirty = true → 不立即重新计算
再次读取: dirty === true → 重新计算 → dirty = false

1.3 computed vs methods

特性computedmethods
缓存
响应式
调用方式属性访问函数调用
副作用不应有可以有

2. watch 执行时机

2.1 默认行为

const count = ref(0);

watch(
  count,
  (newVal, oldVal) => {
    console.log('watch 触发:', newVal);
  },
  { flush: 'pre' }
); // 默认值

count.value = 1;
console.log('同步代码');
// 输出顺序: 同步代码 → watch 触发: 1

2.2 flush 选项

flush 值执行时机用途
preDOM 更新前(默认)修改其他响应式数据
postDOM 更新后访问更新后的 DOM
sync同步执行调试(性能差)
watch(
  count,
  (newVal) => {
    // pre: DOM 还未更新
  },
  { flush: 'pre' }
);

watch(
  count,
  (newVal) => {
    // post: DOM 已更新,可安全访问
    document.getElementById('counter').textContent;
  },
  { flush: 'post' }
);

2.3 immediate 选项

watch(
  source,
  (newVal, oldVal) => {
    // 创建时立即执行一次
  },
  { immediate: true }
);

2.4 deep 选项

const state = reactive({ nested: { count: 0 } });

watch(
  state,
  (newVal) => {
    // 深层变化也会触发
  },
  { deep: true }
);

// Vue 3.4+ watch 自动深层监听 reactive 对象

3. watchEffect

// 自动追踪依赖
watchEffect(() => {
  console.log(count.value); // 自动追踪 count
});

// 与 watch 的区别
// watchEffect: 自动追踪、立即执行、无旧值
// watch: 显式指定、惰性执行、有旧值

4. 停止侦听器

const stop = watch(source, callback);

// 组件卸载时自动停止
// 手动停止
stop();