1. computed
(计算属性)
computed
适用于基于已有数据计算出新的数据,具有缓存特性,只有当依赖的值发生变化时才会重新计算。
特点:
- 有缓存:如果依赖的值没有变化,多次访问
computed
只会返回之前的计算结果,不会重复执行计算逻辑,提高性能。 - 适用于数据派生:如果某个值可以通过现有的
data
计算得出,建议使用computed
。 - 必须有返回值。
例子:
<script setup>
import { ref, computed } from 'vue';const price = ref(100);
const quantity = ref(2);// 计算总价
const totalPrice = computed(() => {return price.value * quantity.value;
});
</script><template><p>单价: {{ price }}</p><p>数量: {{ quantity }}</p><p>总价: {{ totalPrice }}</p>
</template>
totalPrice
依赖于price
和quantity
,当price
或quantity
变化时,totalPrice
会自动更新。- 由于
computed
具有缓存特性,只有price
或quantity
发生变化时,计算逻辑才会执行。
2. watch
(侦听器)
watch
适用于监听某个数据的变化并执行特定操作,但不返回值,适用于异步操作或在数据变化时执行逻辑。
特点:
- 无缓存,每次监听的值变化时都会执行回调函数。
- 适用于执行副作用操作,如请求接口、操作 DOM、本地存储等。
- 可监听单个值或多个值,并可获取新值和旧值。
例子:
<script setup>
import { ref, watch } from 'vue';const count = ref(0);watch(count, (newValue, oldValue) => {console.log(`count 从 ${oldValue} 变成了 ${newValue}`);
});
</script><template><p>当前值: {{ count }}</p><button @click="count++">增加</button>
</template>
- 当
count
发生变化时,watch
触发回调,输出count
的新旧值。 watch
不会返回计算值,而是用于执行额外逻辑(如日志、API 调用等)。
监听多个值:
watch([price, quantity], ([newPrice, newQuantity], [oldPrice, oldQuantity]) => {console.log(`价格变化:${oldPrice} -> ${newPrice}`);console.log(`数量变化:${oldQuantity} -> ${newQuantity}`);
});
3. computed
vs watch
何时使用?
对比项 | computed | watch |
---|---|---|
是否有返回值 | 有,返回计算后的值 | 无,仅执行副作用 |
是否有缓存 | 有,依赖值不变时不会重新计算 | 无,每次变化都会执行 |
适用于 | 依赖已有数据计算新值 | 监听数据变化并执行逻辑 |
使用场景 | 计算属性、过滤、格式化数据 | 监听数据变化、请求 API、执行副作用 |
使用建议:
- 如果一个值是从其他值派生出来的,优先使用
computed
。 - 如果需要在数据变化时执行异步请求、手动操作 DOM、存储数据等,使用
watch
。
4. watchEffect
(更灵活的 watch
)
Vue 3 还提供了 watchEffect
,它不需要手动指定监听的值,而是自动追踪在回调中使用的响应式数据。
import { ref, watchEffect } from 'vue';const count = ref(0);watchEffect(() => {console.log(`count 发生变化: ${count.value}`);
});
watchEffect
会立即执行一次,并自动追踪count
,当count
变化时,回调会重新执行。- 适用于需要立即执行的副作用逻辑。
总结:
- 计算属性(computed) 用于基于已有数据派生新值,有缓存,提高性能。
- 侦听器(watch) 用于监听数据变化并执行副作用(如 API 请求、DOM 操作等)。
- watchEffect 是更灵活的
watch
,适用于自动追踪依赖项的情况。
选择哪一个取决于你的需求:如果是计算属性,优先 computed
;如果是数据变化触发操作,使用 watch
或 watchEffect
。