vue 3 的 computed 默认带缓存机制,仅当响应式依赖变更时才重新计算;依赖必须是 ref、reactive 或其它 computed,普通变量或解构属性会导致失效;函数需纯净,避免副作用;应细粒度控制依赖并正确使用(无括号)。

Vue 3 的 computed 本身就是为了避免不必要的重复计算而设计的——它默认就带缓存机制,只要依赖没变,多次读取 .value 就直接返回缓存值,不会重新执行函数。
依赖必须是响应式数据
这是最关键的前置条件。只有 ref、reactive 对象里的属性、或其它 computed 属性,才能被正确追踪。如果依赖的是普通 JS 变量、函数参数、或非响应式对象字段,computed 就无法感知变化,可能“该更新时不更新”,也可能因依赖丢失而意外缓存过久。
- ✅ 正确:用
ref或reactive包裹原始数据 - ❌ 错误:直接依赖
const list = [{ done: true }]这样的普通数组(哪怕它内容变了,computed 也看不到) - ⚠️ 注意:从 reactive 对象里解构出来的属性会失活,应始终通过对象访问,比如
state.count而不是const { count } = state
避免在计算逻辑中引入副作用或外部依赖
computed 函数体内应保持纯净:只读取响应式依赖,不修改它们,也不调用会产生副作用的函数(如 console.log、api.get()、Date.now() 等)。否则不仅破坏缓存语义,还可能导致结果不可预测。
- ❌ 不推荐:在计算函数里写
console.log('recomputing...')—— 它会干扰调试判断,且暗示逻辑不纯 - ❌ 危险:依赖
new Date()或Math.random()—— 每次访问都不同,但 computed 不会自动重算,结果反而“假稳定” - ✅ 替代方案:需要实时时间可用
watchEffect;需要随机值可封装为独立函数,在模板中按需调用
合理控制依赖粒度
有时候“重复计算”其实是依赖太宽泛导致的。比如你只关心数组长度,却整个引用了数组对象;或者只关注某个字段,却监听了整个表单对象。
- ? 建议:用
toRef或computed做细粒度提取,例如:const itemLength = computed(() => list.value.length)
比computed(() => list.value.map(...))更轻量,触发更新的条件更精准 - ? 复杂场景可拆分:把大计算拆成多个小 computed,各自追踪最小依赖集,提升局部更新效率
不要在模板中误用为方法调用
常见误区:把 computed 当作函数写成 {{ myComputed() }}。这会让 Vue 当作普通方法处理,失去缓存能力,每次渲染都执行。
- ✅ 正确写法:
{{ myComputed }}(无括号,直接读 .value) - ✅ 在 script 中访问:
myComputed.value - ❌ 错误写法:
{{ myComputed() }}或myComputed.value()
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











