pinia getter 缓存基于响应式依赖自动追踪与复用,仅在纯同步、仅依赖响应式数据、返回稳定引用时生效;推荐函数式或 this 式写法,避免模板中直接计算,应拆分复杂逻辑以提升缓存效率。

缓存生效的底层条件
Getter 缓存只在满足以下三点时稳定工作:
-
纯同步计算:不能含
await、setTimeout或 API 调用,否则无法确定何时重算 -
仅依赖响应式数据:只能读取
state或其他getter(通过this),不能读取Date.now()、Math.random()这类非响应式外部值 -
返回稳定引用:避免每次返回新对象/数组,例如不要写
() => ({ ...state.obj });如需结构变换,优先用toRef或保持原始引用
不同写法对缓存的影响
写法决定缓存粒度和复用能力:
-
函数式写法(推荐用于简单派生):
fullName: (state) => `${state.firstName} ${state.lastName}`—— 依赖明确、轻量、默认缓存有效 -
this 式写法(适合链式复用):
activeItems() { return this.items.filter(i => i.active) }和activeCount() { return this.activeItems.length }—— 后者复用前者缓存结果,避免二次遍历 -
带参 Getter(需手动管理缓存):
tasksByStatus: (state) => (status) => state.tasks.filter(t => t.status === status)—— Pinia 不为不同status值分别缓存,高频调用建议搭配lodash.memoize封装
和组件配合才能真正省掉渲染
缓存再好,如果组件里乱写逻辑,也白搭:
- 别在模板里写
v-if="store.items.filter(i => i.done).length"—— 每次渲染都执行,完全绕过 getter 缓存 - 应在 store 中定义
doneCount: (state) => state.items.filter(i => i.done).length - 组件中用
storeToRefs解构:const { doneCount } = storeToRefs(store),模板直接用{{ doneCount }} - 这样既语义清晰,又确保每次读取都走缓存路径,组件也只在
doneCount真正变化时更新
拆分比堆砌更高效
一个复杂 getter 容易让缓存“太敏感”或“太迟钝”:
- 错误做法:把过滤、排序、分页全塞进一个
filteredSortedPagedList() - 正确做法:拆成
filteredItems()→sortedItems()→pagedItems(),每个环节独立缓存,Pinia 只重算真正受影响的部分 - 哪怕多写几行,性能和可维护性都明显提升










