跳到主要内容

Vue 中 computed 和 watch 的区别

面试速答(30 秒版 TL;DR)

  • computed:用于“派生状态”(由其他响应式数据计算得到),有缓存,依赖不变就不重复计算。
  • watch:用于“副作用”(请求、埋点、手动操作 DOM、写入 storage),监听变化后执行回调。
  • 一句话:能用 computed 就别用 watch 去算值;需要副作用才用 watch。

computed:派生状态 + 缓存

import { computed, ref } from 'vue';

const price = ref(100);
const count = ref(2);

const total = computed(() => price.value * count.value);

特点:

  • total 会缓存上一次的结果,只有依赖(price/count)变化才重新计算。
  • 更符合“声明式 UI”:模板用 total,不关心它怎么来的。

watch:监听变化做副作用

import { ref, watch } from 'vue';

const keyword = ref('');

watch(keyword, async (newVal, oldVal) => {
if (!newVal) return;
// 例如:发请求
});

常用配置(Vue 3):

  • immediate: true:一上来就执行一次
  • deep: true:深度监听对象(代价更高)
  • flush: 'post' | 'pre' | 'sync':控制回调在更新周期中的时机

常见追问

Q1:watchEffect 和 watch 的区别?

  • watch:显式指定依赖源,回调有新旧值。
  • watchEffect:自动收集依赖,适合“依赖源不固定或很多”的副作用,但不直接给 oldValue。

Q2:能不能用 watch 去实现 computed?

能但不推荐。watch 更像“命令式同步”,容易漏依赖、产生竞态;computed 是“声明式派生”,更稳定可维护。