WinlatorXR
881.97M · 2026-02-04
在 Vue 的响应式世界里,computed(计算属性)和 watch(侦听器)是我们处理数据联动最常用的两把利器。虽然它们都能响应数据变化,但背后的设计哲学和应用场景却大相径庭。本文将结合 Vue 3 组合式 API 与 TypeScript,带你理清两者的本质区别。
computed 的核心在它是一个计算属性。它会根据所依赖的数据动态计算结果,并具备强大的缓存机制。
return 返回计算后的结果。<script setup lang="ts">
import { ref, computed } from 'vue';
const count = ref<number>(1);
// computedValue1 为计算出的新属性
const computedValue1 = computed<number>(() => {
console.log('正在执行计算...'); // 只有 count 改变时才会打印
return count.value + 1;
});
</script>
<template>
<div>原值: {{ count }} | 计算值: {{ computedValue1 }}</div>
<button @click="count++">增加</button>
</template>
watch 的核心在于响应副作用。当的值发生改变时执行特定的回调函数。
无缓存性:它不是为了产生新值,而是为了在值变化时执行逻辑。
无返回值:回调函数中通常处理的是异步操作、修改 DOM 或更改其他状态。
配置灵活:
immediate:设置为 true 时,在初始化时立即执行一次。deep:设置为 true 时,可以深度对象内部属性的变化。<script setup lang="ts">
import { ref, watch } from 'vue';
interface UserInfo {
name: string;
age: number;
}
const user = ref<UserInfo>({ name: '张三', age: 25 });
// 对象深度变化
watch(
user,
(newVal, oldVal) => {
// 注意:由于是引用类型,newVal 和 oldVal 指向的是同一个对象,只有开启deep: true才能到
console.log('用户信息变了', newVal.age);
},
{
deep: true, // 开启深度
immediate: false // 初始化时不立即执行
}
);
</script>
在 Vue 3 中,除了 watch,还有一个更自动化的 watchEffect。
watchEffect 不需要手动指定哪个属性,它会自动收集回调函数中用到的所有响应式变量。watchEffect 代码更简洁。<script setup lang="ts">
import { ref, watchEffect } from 'vue';
const user = ref({ name: '张三', age: 25 });
// watchEffect 会自动追踪依赖
watchEffect(() => {
console.log('watchEffect age:', user.value.age);
// 自动收集 user.value.age 作为依赖
// 当 age 变化时会自动执行
});
</script>
| 特性 | Computed (计算属性) | Watch (侦听器) |
|---|---|---|
| 主要功能 | 生成一个新属性(派生状态) | 响应数据变化并执行代码(副作用) |
| 缓存 | 有缓存,依赖不变不计算 | 无缓存,变化即触发 |
| 异步 | 不支持异步逻辑 | 支持异步操作(如接口请求) |
| 代码结构 | 必须有 return | 不需要 return |
| 使用场景 | 格式化数据、多值组合、性能优化 | 异步数据请求、手动操作 DOM、路由变化 |