Vue 3 中 computed 默认具备缓存特性,前提是 getter 仅访问响应式数据(如 ref.value、reactive 属性等),避免副作用、非响应式变量及深层响应丢失。

在 Vue 3 中,编写具有缓存特性的计算属性,核心是使用 computed 函数,并确保它作用于响应式数据(如 ref、reactive 或其嵌套属性)。缓存不是手动开启的开关,而是 computed 的默认行为——只要写法合规,缓存自动生效。
必须基于响应式源数据
计算属性的缓存依赖 Vue 的依赖追踪系统。只有当内部访问的是真正的响应式值时,Vue 才能建立依赖关系并实现“依赖不变就不重算”。
- ✅ 正确:读取
ref的.value、reactive对象的属性、toRef创建的引用 - ❌ 错误:传入普通 JS 变量、解构后的非响应式副本(如
const { count } = reactive({ count: 0 }))、或从 props 直接解构未用toRef包装的值 - 示例:
<script setup>
import { ref, computed } from 'vue'
const list = ref([{ done: true }, { done: false }])
// ✅ 缓存有效:list 是 ref,.value 是响应式数组
const completedCount = computed(() => list.value.filter(i => i.done).length)
</script>
避免在 getter 中产生副作用或外部依赖
缓存机制假设计算逻辑是纯函数:输出只由响应式输入决定。一旦引入非响应式变量、定时器、全局状态、或异步等待,缓存就可能失效或行为异常。
Vue 3 组合式 API 与 最佳实践,涵盖代码组织、useXxx 模式、组合式函数设计、Store 集成、响应式优化及功能抽取。
- 不要在
computed的 getter 里调用setTimeout、fetch、console.log(调试除外)或修改其他响应式数据 - 不要依赖未声明为响应式的外部常量(如
const API_BASE = '/api'是安全的;但let userToken就不行) - 若需条件判断,确保所有分支都只读响应式数据,不隐式引入新依赖
合理使用只读 vs 可写计算属性
大多数场景用只读形式即可,它天然具备完整缓存;可写形式(传入对象含 get 和 set)缓存仅作用于 get,且 set 中不应触发新计算。
立即学习“前端免费学习笔记(深入)”;
- 只读(推荐):
computed(() => xxx)—— 简洁、缓存稳定、适合展示类逻辑 - 可写:
computed({ get() {}, set(val) {} })—— 仅在需要双向绑定派生值时使用,例如格式化输入框内容 - 注意:可写计算属性的
get仍享受缓存,但set不参与缓存逻辑,也不应修改自身依赖项
警惕缓存“看似失效”的常见情况
不是缓存坏了,而是依赖没被正确捕获:
- 数组/对象深层属性未通过响应式方式访问:比如
arr[0].name在arr是ref([])时是响应的;但如果arr是普通数组,就不会触发更新 - 使用了非响应式工具方法:如
Object.assign({}, obj)后再读属性,会丢失响应性 - 在
computed内部调用了无响应式包装的函数(例如封装在utils.js里的纯函数没问题,但若该函数内部又读取了另一个ref却没被computed直接访问,那这个依赖就不会被收集)

















