第 15 题:computed vs watch 区别 + 使用场景
🎯 一、标准回答(面试官必答点)
| 特性 | computed | watch |
|---|---|---|
| 依赖收集 | 自动依赖追踪 | 需要手动指定依赖 |
| 返回值 | 会缓存(lazy evaluation) | 不缓存 |
| 用途 | 计算衍生数据 | 执行副作用(API、DOM操作等) |
| 执行时机 | 访问时才执行 | 数据变化时触发 |
| 获取 oldValue | ❌ | ✔ 可以获取 |
| 适用场景 | 纯计算逻辑 | 监听变化做异步或副作用处理 |
🎯 二、代码示例
1️⃣ computed 示例(缓存计算)
xml
<script setup>
import { ref, computed } from 'vue'
const count = ref(1)
const double = computed(() => count.value * 2)
console.log(double.value) // 2
count.value++
console.log(double.value) // 4,computed 会自动更新并缓存
</script>
特点:
- 只有访问
double.value时才执行 - 如果依赖未变化,直接返回缓存值
2️⃣ watch 示例(副作用监听)
xml
<script setup>
import { ref, watch } from 'vue'
const count = ref(1)
watch(count, (newVal, oldVal) => {
console.log(`count changed from ${oldVal} to ${newVal}`)
})
count.value++ // 触发 watch 回调
特点:
- 触发副作用(日志、请求 API、操作 DOM)
- 可以获取
oldVal - 默认 flush: 'pre'(可指定 post 或 sync)
🎯 三、面试官追问(高频)
追问 1:computed 能做异步吗?
答:
- computed 不支持异步(只计算同步逻辑)
- 异步逻辑应该用
watch或watchEffect
追问 2:computed 的懒执行原理?
答:
- 内部依赖收集 + dirty flag
- 依赖变化时标记 dirty = true
- 下次访问 value 时才重新计算并缓存结果
追问 3:computed vs watchEffect 区别?
| 特性 | computed | watchEffect |
|---|---|---|
| 返回值 | 缓存返回值 | 无返回值 |
| 依赖 | 自动收集 | 自动收集 |
| 执行时机 | 访问 value 时才执行 | 默认立即执行一次 |
| 用途 | 衍生数据 | 副作用逻辑 |
追问 4:watch 可以替代 computed 吗?
答:
- 技术上可以,但不推荐
- watch 不缓存,每次访问都可能重新执行
- computed 更轻量且性能高
追问 5:computed 可以和 ref 联动吗?
scss
const count = ref(1)
const double = computed(() => count.value * 2)
double.value++ // ❌ 报错,computed 默认只读
- 解决方法 :使用
computed({ get, set })创建可写 computed
dart
const double = computed({
get: () => count.value * 2,
set: val => count.value = val / 2
})
🎯 四、一句话总结(背面试官即可)
computed 用于缓存衍生数据,懒执行、自动依赖收集;watch 用于监听数据变化触发副作用,可获取新旧值。computed 更轻量,watch 更灵活,适合异步或副作用逻辑。