computed 用于声明式创建只读响应式派生值,自动追踪依赖并缓存结果;watch 用于监听响应式数据变化并执行副作用,支持多种监听模式和执行时机控制。

在 Vue 3 的 Composition API 中,computed 和 watch 不再是选项式 API 中的配置项,而是可导入、可组合的函数,它们的行为逻辑更贴近响应式系统的底层机制,也更灵活。
computed:声明式地创建响应式派生值
computed 用于基于响应式数据(如 ref 或 reactive)推导出一个只读的响应式值。它会自动追踪依赖,并在依赖变化时重新求值。
用法上需注意两点:一是必须传入一个 getter 函数;二是返回值是 Ref 类型(即使你传入的是对象,也要通过 .value 访问)。
- 基础用法:
const double = computed(() => count.value * 2),其中count是ref(1) - 支持 setter(仅限双绑场景):
computed({ get() {}, set(val) {} }),常用于封装双向绑定逻辑 - 不可直接赋值:
double.value = 10会报错(除非显式定义了 setter)
watch:执行副作用,响应数据变化
watch 用于监听响应式数据的变化,并在变化时运行回调函数。它不返回值,专注“做某事”,比如发送请求、更新 DOM、触发动画等。
递归分析 Vue 项目组件依赖,从入口文件生成组件层级图,支持 Vue 2/3,输出组件名、文件路径和属性。适用于分析组件结构、排查依赖或了解项目架构。
立即学习“前端免费学习笔记(深入)”;
与 computed 的被动派生不同,watch 是主动的副作用管理工具,且支持多种监听模式。
- 监听单个 ref:
watch(count, (newVal, oldVal) => { console.log(newVal) }) - 监听 reactive 对象的深层属性:
watch(() => state.user.name, ...)或配合deep: true - 监听多个来源:
watch([refA, refB], ([a, b], [prevA, prevB]) => {...}) - 支持
immediate: true实现立即执行,以及flush: 'post' | 'sync'控制执行时机
关键区别:用途、返回值与响应时机
computed 是同步派生,强调“是什么”;watch 是异步响应,强调“做什么”。两者不可互换,但常配合使用。
-
computed的值在模板中访问或 JS 中读取时才计算(惰性求值),且结果被缓存 -
watch的回调默认在组件更新后异步执行(flush: 'post'),适合操作 DOM 或发起副作用 - 不要在
watch里重复computed的逻辑——该派生就派生,该响应才响应 - 避免在
computed中执行副作用(如调用 API、修改 ref),这会破坏响应式链的纯净性
进阶技巧:watchEffect 与 computed 的协同
watchEffect 是 watch 的简化版:它自动收集依赖,无需显式指定监听源。适合“只要这些值变了,就重跑这段逻辑”的场景。
-
watchEffect(() => console.log(name.value, age.value))—— 自动追踪name和age - 搭配
onInvalidate可处理异步竞态(如防抖请求、取消 pending 请求) - 当派生逻辑复杂且含副作用时,可用
computed提取纯计算部分,再用watchEffect响应其变化

















