Vue 3 中 computed 和 watch 的区别 + 原理 + 写法详解

🧠 Vue 3 中 computed 和 watch 的区别 + 原理 + 写法详解

📌 整理不易,记得收藏、点赞、关注,掌握 Vue 响应式系统的精髓!

在 Vue 开发中,computedwatch 是常用的响应式工具。它们看似类似,但实际使用场景与工作机制完全不同。

本文将带你从 概念、使用场景、核心原理、写法对比 等多个维度掌握它们,助你写出更高效的响应式代码。


🎯 一、computed 和 watch 的核心区别

对比点computed(计算属性)watch(监听器)
📌 用途声明式地返回派生数据响应式地观察数据变化并执行副作用操作
🧠 原理缓存 + 懒执行立即执行回调函数
📦 是否缓存✅ 默认缓存(依赖不变不重新计算)❌ 不缓存,数据变了就触发
🔁 响应行为自动追踪依赖,依赖变时重新计算依赖变化后执行提供的函数
💡 适用场景显示计算值,如模板绑定、组件数据执行副作用操作,如请求数据、手动处理逻辑等
🧪 模板使用直接使用,如 {{ fullName }}无法用于模板中,主要用于监听逻辑处理

🧩 二、watch 的实现原理(Vue 3 Composition API)

在 Vue 3 中,watch 是通过内部的 EffectScope + ReactiveEffect 实现的。

简化流程如下:

  1. 建立依赖收集

    • watch(source, callback) 会根据 source 类型建立依赖追踪(getter/Ref/reactive)。
  2. 创建 ReactiveEffect 副作用函数

    • Vue 会将 source 包裹成响应式 getter 函数。
    • 利用副作用(effect)机制监听变化。
  3. 触发回调

    • source 中依赖的数据变化时,调用 callback(newVal, oldVal)
  4. 调度执行

    • 默认异步执行(microtask),也可以配置 flush: 'sync' 立即同步执行。

✍️ 三、watch 的三种写法(Vue 3)

✅ 1. 基本写法(监听一个 ref)

const count = ref(0)watch(count, (newVal, oldVal) => {console.log('count changed:', oldVal, '→', newVal)
})

适合监听 refreactive.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