🧠 Vue 3 中 computed 和 watch 的区别 + 原理 + 写法详解
📌 整理不易,记得收藏、点赞、关注,掌握 Vue 响应式系统的精髓!
在 Vue 开发中,computed 和 watch 是常用的响应式工具。它们看似类似,但实际使用场景与工作机制完全不同。
本文将带你从 概念、使用场景、核心原理、写法对比 等多个维度掌握它们,助你写出更高效的响应式代码。
🎯 一、computed 和 watch 的核心区别
| 对比点 | computed(计算属性) | watch(监听器) |
|---|---|---|
| 📌 用途 | 声明式地返回派生数据 | 响应式地观察数据变化并执行副作用操作 |
| 🧠 原理 | 缓存 + 懒执行 | 立即执行回调函数 |
| 📦 是否缓存 | ✅ 默认缓存(依赖不变不重新计算) | ❌ 不缓存,数据变了就触发 |
| 🔁 响应行为 | 自动追踪依赖,依赖变时重新计算 | 依赖变化后执行提供的函数 |
| 💡 适用场景 | 显示计算值,如模板绑定、组件数据 | 执行副作用操作,如请求数据、手动处理逻辑等 |
| 🧪 模板使用 | 直接使用,如 {{ fullName }} | 无法用于模板中,主要用于监听逻辑处理 |
🧩 二、watch 的实现原理(Vue 3 Composition API)
在 Vue 3 中,watch 是通过内部的 EffectScope + ReactiveEffect 实现的。
简化流程如下:
-
建立依赖收集:
watch(source, callback)会根据source类型建立依赖追踪(getter/Ref/reactive)。
-
创建 ReactiveEffect 副作用函数:
- Vue 会将
source包裹成响应式 getter 函数。 - 利用副作用(effect)机制监听变化。
- Vue 会将
-
触发回调:
- 当
source中依赖的数据变化时,调用callback(newVal, oldVal)。
- 当
-
调度执行:
- 默认异步执行(microtask),也可以配置
flush: 'sync'立即同步执行。
- 默认异步执行(microtask),也可以配置
✍️ 三、watch 的三种写法(Vue 3)
✅ 1. 基本写法(监听一个 ref)
const count = ref(0)watch(count, (newVal, oldVal) => {console.log('count changed:', oldVal, '→', newVal)
})
适合监听 ref 或 reactive.xxx 属性。
✅ 2. 多个数据一起监听(数组写法)
const x = ref(1)
const y = ref(2)watch([x, y], ([newX, newY], [oldX, oldY]) => {console.log('x or y changed:', newX, newY)
})
用于组合多个响应式数据。
✅ 3. 函数式写法(计算依赖)
const user = reactive({ first: 'Jin', last: 'Chen' })watch(() => user.first + ' ' + user.last,(newFullName, oldFullName) => {console.log('Full name changed:', oldFullName, '→', newFullName)}
)
适合监听复杂表达式或多个依赖组合结果。
✨ watch 的高级选项
watch(source, callback, {immediate: true, // 立即执行一次deep: true, // 深度监听(适用于对象/数组)flush: 'post', // post(默认)、pre、sync
})
📚 四、computed 的写法与行为说明
✅ 基本写法
const count = ref(1)
const double = computed(() => count.value * 2)
- 自动追踪
count.value,发生变化时重新计算double - 有缓存,
count不变时多次访问不会重复计算
✅ 具有 getter / setter 的计算属性
const name = ref('Jin')
const upperName = computed({get: () => name.value.toUpperCase(),set: val => {name.value = val.toLowerCase()}
})upperName.value = 'HELLO' // name 变成 'hello'
🧠 五、总结一句话
computed用于返回值,适合绑定模板、计算派生数据。watch用于执行副作用,适合监听变化后做某事。
📌 选择口诀:
- 想要“返回一个值”?用
computed - 想要“监听变化做事”?用
watch