computed 依赖响应式数据缓存结果,仅在依赖变更时重新计算;解构响应式对象、忽略非响应式函数副作用、动态 key 访问不当会破坏依赖追踪,导致缓存失效或视图不同步。

Vue.js 的 computed 计算属性不是每次访问都重新执行,而是基于其依赖的数据进行响应式缓存——只要依赖未变,就直接返回上一次计算结果。这是它区别于 methods 的核心优势,也是性能优化的关键起点。
缓存触发条件:依赖追踪与响应式更新
computed 在初始化时会主动执行一次,期间 Vue 会通过 getter 中的响应式数据访问(如 this.count、this.list.length)自动收集依赖。之后只有当这些被追踪的响应式属性发生变更(即触发 setter 并通知依赖更新),该 computed 才会重新求值。
- 普通对象属性、ref、reactive 数据会被正确追踪
- 非响应式变量(如局部 const、Math.random()、Date.now())不会触发更新,也不参与缓存判断
- 异步操作(如 await、setTimeout 回调内修改)本身不构成依赖,但若修改了响应式数据,会间接触发更新
避免缓存失效的常见陷阱
缓存失效往往不是因为机制失灵,而是写法破坏了依赖追踪链:
-
不要在 computed 中解构响应式对象:
const { name, age } = this.user→ 解构后 name/age 变成普通变量,不再响应;应改为this.user.name直接访问 -
避免在计算中调用非响应式函数并忽略返回值:
doSomething(); return this.a + this.b—— 若doSomething内部修改了响应式数据,但未在依赖中体现,会导致视图不同步 -
慎用数组索引或动态 key 访问:
this.items[index]是可追踪的;但this.items[this.activeKey]中若this.activeKey未变化,即使this.items被整个替换,也可能漏掉更新(建议配合JSON.stringify或使用 markRaw 配合 watch 处理极端场景)
结合场景做有效优化:什么该用 computed,什么不该
不是所有派生数据都适合用 computed。合理选择能真正发挥缓存价值:
立即学习“前端免费学习笔记(深入)”;
-
适合 computed:过滤列表(
this.list.filter(x => x.status === 'active'))、格式化日期(dayjs(this.timestamp).format('YYYY-MM-DD'))、组合多个 prop 计算状态(this.loading && !this.data.length) -
更适合 methods:需要传参的逻辑(如
getById(id))、含副作用的操作(如发请求、改 localStorage)、实时性要求极高且依赖不可靠的场景(如读取 window.innerWidth) - 可搭配 watchEffect 提升灵活性:当计算逻辑含异步或需手动控制执行时机时,watchEffect 能自动追踪依赖并执行,比强行塞进 computed 更清晰
高级技巧:缓存调试与强制更新
开发中可通过以下方式验证或干预缓存行为:
- 在 computed getter 中加
console.log('recalculated'),观察是否重复打印,快速判断是否命中缓存 - 使用 Vue Devtools 查看组件的 computed 列表,点击可查看当前值、依赖项及是否“cached”
- 极少数需绕过缓存(如强制刷新时间显示),可用
key重置组件,或改用 ref + watch 实现可控更新,而非破坏 computed 设计初衷
理解 computed 的缓存本质,不是为了“省几毫秒”,而是让数据流更可预测、视图更新更精准。写得越贴近响应式范式,Vue 就越能帮你把性能兜住。



















