Vue3 中 computed、watch、watchEffect 的区别?
computed(计算属性)
基于其他响应式数据派生新值,有缓存,只有依赖变化时才重新计算。
const count = ref(0)
const double = computed(() => count.value * 2)
// 只有 count 变化时 double 才重新计算
// 多次访问 double 只计算一次(缓存)
// 可写 computed
const fullName = computed({
get: () => `${first.value} ${last.value}`,
set: (val) => {
[first.value, last.value] = val.split(' ')
}
})watch(侦听器)
监听响应式数据变化,执行副作用。需要明确指定监听目标,有旧值和新值。
// 监听 ref
watch(count, (newVal, oldVal) => {
console.log(`count: ${oldVal} → ${newVal}`)
})
// 监听 reactive 属性(需要 getter 函数)
watch(() => state.count, (newVal, oldVal) => {
console.log(newVal)
})
// 监听多个
watch([count, () => state.name], ([newCount, newName]) => {
console.log(newCount, newName)
})
// 配置选项
watch(count, callback, {
immediate: true, // 立即执行一次
deep: true, // 深度监听
flush: 'post' // DOM 更新后执行
})watchEffect(立即执行侦听器)
自动收集依赖,不需要指定监听目标。立即执行一次,然后依赖变化时重新执行。
// 自动追踪 count 和 name
watchEffect(() => {
console.log(count.value, name.value)
})
// 清理副作用
watchEffect((onCleanup) => {
const timer = setInterval(() => {
console.log(count.value)
}, 1000)
onCleanup(() => clearInterval(timer))
})对比
| 特性 | computed | watch | watchEffect |
|---|---|---|---|
| 返回值 | ✅ 返回新值 | ❌ | ❌ |
| 缓存 | ✅ | ❌ | ❌ |
| 立即执行 | ❌ | 默认❌(可 immediate) | ✅ |
| 指定监听 | 自动收集 | ✅ 手动指定 | 自动收集 |
| 获取旧值 | ❌ | ✅ | ❌ |
| 适合 | 派生数据 | 需要旧值的副作用 | 简单副作用 |
使用场景
// computed:派生数据
const filteredList = computed(() =>
list.value.filter(item => item.includes(keyword.value))
)
// watch:需要旧值或精确控制
watch(selectedId, (newId, oldId) => {
if (newId !== oldId) fetchData(newId)
}, { immediate: true })
// watchEffect:简单副作用
watchEffect(() => {
document.title = `${count.value} items`
})性能注意
- computed 有缓存,优先使用
- watch 的
deep: true性能开销大,谨慎使用 - watchEffect 自动追踪依赖,但不够显式