前端进阶之旅前端进阶之旅
  • 基础篇HTML/CSS/JS 打底
  • 进阶篇原理与工程化
  • 高频篇面试最常问的那批
  • 精选篇按模块收敛的总结
  • 手写篇常考代码手写实现
  • 面经篇真实面试问题复盘
  • AI 篇NEWAI 时代的前端考点
  • 历年面经NEW按年份追踪真实考点
  • 每日一题每天一道,攒手感
  • 专项自测100 题快速查漏
  • 小程序题库小程序专项刷题
  • 算法题库NEW在线编码即时判题
  • 知识卡片NEW碎片时间过考点
  • 面试题大全常见问题解析
  • AI 答疑NEW随时提问,即时解析
  • AI 模拟面试NEW模拟真实面试 + 报告
  • AI 定制路线NEW按你的简历现排
  • AI 知识地图NEW串起全站知识点
  • 原理篇React / Vue 源码拆解
  • HTTP从报文一路讲到 HTTPS
  • 浏览器渲染、事件循环、进程
  • 计算机基础Linux、网络、操作系统
  • 设计模式23 种模式怎么用
  • Node学习指南从环境搭建到服务端
  • NPM工作流script、依赖与发布
  • Docker容器化部署上手
  • Canvas图形与动画实战
  • 前端系统进阶学习大型项目工程化
  • 前端综合文章长期沉淀的实践文
  • 思维导图知识点全景图
  • 学习路线按图索骥不跑偏
  • AI 热点NEWAI 每日动态
  • 公众号动态公众号历史文章
  • 博客动态站长的技术博客
  • 开发者导航常用工具与文档站
  • 基础篇HTML/CSS/JS 打底
  • 进阶篇原理与工程化
  • 高频篇面试最常问的那批
  • 精选篇按模块收敛的总结
  • 手写篇常考代码手写实现
  • 面经篇真实面试问题复盘
  • AI 篇NEWAI 时代的前端考点
  • 历年面经NEW按年份追踪真实考点
  • 每日一题每天一道,攒手感
  • 专项自测100 题快速查漏
  • 小程序题库小程序专项刷题
  • 算法题库NEW在线编码即时判题
  • 知识卡片NEW碎片时间过考点
  • 面试题大全常见问题解析
  • AI 答疑NEW随时提问,即时解析
  • AI 模拟面试NEW模拟真实面试 + 报告
  • AI 定制路线NEW按你的简历现排
  • AI 知识地图NEW串起全站知识点
  • 原理篇React / Vue 源码拆解
  • HTTP从报文一路讲到 HTTPS
  • 浏览器渲染、事件循环、进程
  • 计算机基础Linux、网络、操作系统
  • 设计模式23 种模式怎么用
  • Node学习指南从环境搭建到服务端
  • NPM工作流script、依赖与发布
  • Docker容器化部署上手
  • Canvas图形与动画实战
  • 前端系统进阶学习大型项目工程化
  • 前端综合文章长期沉淀的实践文
  • 思维导图知识点全景图
  • 学习路线按图索骥不跑偏
  • AI 热点NEWAI 每日动态
  • 公众号动态公众号历史文章
  • 博客动态站长的技术博客
  • 开发者导航常用工具与文档站
首页程序员面试题库Vue computed 缓存失效和依赖追踪
VuVue响应式原理

Vue computed 的缓存什么时候失效,无关状态更新会重新计算吗?

computed 的缓存依据 getter 实际读取的响应式依赖,不能把组件每次更新等同于 getter 每次执行。

前端进阶之旅 · 一题精讲更新于 2026.09.06
Vue#响应式原理#缓存
先看核心答案读代码示例
理解线索

一次计算与后续读取如何对应

  1. 读取来源本次 getter 执行访问到哪些响应式属性
  2. 缓存复用这些输入仍有效时可以继续使用已有结果
  3. 重新取值相关输入变化后,在需要结果时重新检查并计算

不要为验证缓存而在业务 getter 中写日志上报、请求或响应式状态;getter 应保持纯粹。

核心回答

先记住这个答案

computed 在 getter 执行时追踪响应式读取,并复用依赖未变化时的计算结果。相关依赖变化后,后续取值会按需要刷新结果;组件因为其它状态更新,并不意味着这个 computed 必须重新计算。依赖来自实际执行路径,普通时间函数或未经过响应式入口的变化不会自动让缓存更新。同时要区分 getter 重新求值和下游组件更新,派生结果仍相同时不应推导所有消费者都必须重做工作。

  • 追踪 getter 实际读取的响应式来源
  • 无关状态改变不自动使该计算结果失效
  • 依赖失效、求值和下游更新是不同环节

无关输入更新不应扩大计算依赖

一个购物页面用 quantity 和 unitPrice 计算价格摘要,旁边还有搜索框状态。只要价格 getter 没有读取搜索词,搜索变化不应仅因同一个组件更新就成为价格计算的依赖。相反,如果 getter 无意中遍历了包含所有页面配置的对象,就可能扩大实际读取范围。

下面例子让 computed 返回一个新对象,通过结果引用比较观察缓存是否复用。无关 noise 改变后仍能读到同一份结果;quantity 变化后读取到新的摘要对象。业务代码不应依赖缓存对象身份作为永久实体 ID,这里只是用可观察行为解释缓存关系。

无关变化与实际依赖变化分别读取TypeScript
import { computed, reactive } from 'vue';

const state = reactive({ quantity: 2, unitPrice: 10, noise: 0 });
const summary = computed(() => ({ total: state.quantity * state.unitPrice }));
const first = summary.value;
const repeated = summary.value === first;
state.noise++;
const afterNoise = summary.value === first;
state.quantity = 3;
const afterQuantity = summary.value;
const result = { repeated, afterNoise, replaced: afterQuantity !== first, total: afterQuantity.total };

Vue 3 中 result 的三个布尔值均为 true,total 为 30。通过结果引用观察缓存复用,没有在 getter 内修改计数器,也没有声明固定控制台输出。

条件分支会改变本轮读取的来源

例如价格 getter 根据 useDiscount 选择原价或折扣价,实际走到的分支决定本轮还读取哪些字段。分支条件本身也会被追踪;切换条件后重新执行 getter,依赖关系会按新的读取路径更新。不能仅凭函数源码里出现过某个字段,就认定它在所有时刻都触发这份计算。

Date.now 或普通外部变量没有自动提供响应式通知。如果要显示持续变化的时间,可以维护明确的时间 ref 并安排更新与清理,让 computed 从这个输入派生展示。不能把时间函数放进 computed 后期待缓存按照墙上时钟自然过期,也不能把它当成带有效期的网络缓存。

计算结果变化与消费者工作要分别观察

相关依赖改变意味着结果需要重新检查,但若重新求出的值与之前相同,下游工作不一定都需要重新执行。Vue 对 computed 稳定性的优化有具体版本边界;分析性能时应分别观察输入、getter 成本与消费者结果,避免把一个依赖通知等同于整片界面重绘。

若 getter 每次都返回新的对象,即使业务字段内容相同,也可能破坏结果稳定性。优化时先保持计算纯粹,再根据实际成本考虑返回值结构和稳定复用,不能为了复用旧对象而跳过本轮必要的依赖读取。渲染调度也不应被简化为每次赋值立即完成一次 DOM 更新。

回答前,多想一步

容易答错的地方

computed 就是只在组件第一次挂载时算一次
它会围绕响应式依赖重新求值,并不是固定初始化缓存。首次结果正确不代表之后不再更新,应通过修改实际输入验证计算是否仍与数据一致。
对象深处任何字段改变都会让 computed 失效
需要看 getter 实际读取了什么,以及变化是否经过响应式系统。只读取对象引用与读取某个深层属性的依赖范围不同,不能用深响应式概念替代具体读取分析。
试着用自己的话回答

面试官还会怎么问?

computed 从没被读取,也必须立即执行 getter 吗?

computed 具有按需计算的特征,不应依赖创建它时就执行某个副作用。需要执行外部同步时,应采用合适的侦听与生命周期机制,而不是把操作藏在 getter 中。

直接改 raw 对象能让 computed 自动失效吗?

绕过代理的写入不会自动经过响应式通知入口,因此不能依赖它触发计算更新。持续通过明确的代理或 ref 修改状态,才能让依赖关系与变化保持一致。

为什么不直接把普通方法当 computed 用?

方法调用按调用流程执行,不提供同样的响应式依赖缓存。是否需要 computed 取决于它是否是适合缓存的纯派生值,而不是因为代码能抽成函数就必须缓存。

从一道题,走向一组知识

把知识连起来

响应式原理

Vue 的 computed 和模板里调用方法都能派生值,什么输入下 computed 的缓存才是决定性优势?

比较 computed 与普通方法的使用选择,避免把两者只看作不同语法。

响应式原理

Vue 可写 computed 的 get 和 set 应怎样配合,为什么 getter 不能改状态?

派生结果需要对外提供写入口时,还要明确 setter 怎样回到源状态。

侦听与生命周期

Vue 什么时候用 watch,什么时候用 computed?

缓存的派生值与变化后执行的外部同步不同,继续判断何时该使用 watch。

参考资料

  • Computed Properties
  • Performance: Computed Stability
  • Reactivity in Depth

示例用于理解所注明的运行环境与边界;延伸学习可结合原文中的更多案例。

本题目录
  1. 先记住这个答案
  2. 无关输入更新不应扩大计算依赖
  3. 条件分支会改变本轮读取的来源
  4. 计算结果变化与消费者工作要分别观察
  5. 容易答错的地方
  6. 面试官还会怎么问
  7. 把知识连起来
读懂,再试着讲出来

先看核心答案,再读代码。最后展开追问,检查自己有没有遗漏边界。

试着回答追问
浏览全部面试题理解原理,也关注真实的使用场景。回到顶部 ↑