computed 和 watch 是 Vue.js 中处理数据变化的两种核心机制,核心区别在于计算方式与适用场景:computed 用于缓存派生值,watch 用于响应数据变化的异步或副作用操作。
核心区别:
缓存机制
- computed 依赖不变时复用缓存结果,避免重复计算。
- watch 每次数据变化都会触发回调,无缓存机制。
异步支持
- computed 不支持异步操作,内部异步代码无效。
- watch 支持异步操作(如 API 请求)。
返回值要求
- computed 必须通过 return 返回值。
- watch 无需返回值,直接执行回调逻辑。
初始化行为
- computed 首次加载自动计算并缓存。
- watch 默认首次不触发,需设置 immediate: true 才初始化执行。
适用场景
- 优先用 computed。
当属性由多个数据派生时(如购物车总价),或需避免重复计算的场景。
- 选择 watch。
当数据变化需执行异步操作(如搜索请求)、复杂副作用,或监听非 Vue 数据源(如 URL 变化)时。
底层原理
两者均基于 Vue 响应式系统:
computed 通过依赖收集实现懒更新,依赖不变时复用缓存。
watch 通过深度监听(deep: true)或精确监听触发回调,但性能消耗较高。
computed 示例:
<template>
姓:<input v-model="firstName">
<br/>
名:<input v-model="lastName">
<br/>
全名:<span> {{ fullName }}</span>
<br/>
<button @click="handleClick">修改全名</button>
</template>
<script setup lang="ts">
import { ref, computed, h } from 'vue';
let firstName = ref('zhang');
let lastName = ref('san');
/* //计算属性------只读取,不修改
let fullName = computed(()=>{
return firstName.value + '-' + lastName.value
}) */
// 计算属性------既读取又修改
let fullName = computed({
// 读取
get(){
return firstName.value.slice(0,1).toUpperCase() + firstName.value.slice(1) + '-' + lastName.value
},
// 修改
set(val){
console.log('有人修改了fullName',val)
firstName.value = val.split('-')[0]
lastName.value = val.split('-')[1]
}
})
function handleClick(){
fullName.value = 'xiao-ming'
}
</script>