pinia getter 缓存优化需拆分计算逻辑、避免副作用、手动记忆化参数化函数,并在组件中通过语义化 getter 和 storetorefs 利用缓存链。

Pinia Getters 本身具备缓存能力,但面对高频、复杂计算(比如大数据过滤、多条件组合搜索、深度嵌套遍历),默认缓存可能不够用,甚至被意外破坏。优化关键在于“让缓存真正生效”和“把重活拆解、节制、隔离”。
拆分 getter,让中间结果可缓存
不要在一个 getter 里完成“过滤 + 搜索 + 排序 + 分页 + 格式化”。Pinia 的缓存是按 getter 粒度工作的——每个 getter 只缓存自己的返回值。拆开后,只要上游没变,下游就不重算。
-
filteredTasks:只依赖
state.tasks和state.statusFilter,返回过滤后的数组 -
searchedTasks:依赖
this.filteredTasks和state.keyword,只做字符串匹配 -
pagedTasks:依赖
this.searchedTasks和state.page、state.pageSize,只切片
避免缓存失效的常见陷阱
以下写法会让 Pinia 无法识别依赖变化,导致每次访问都重新执行,失去缓存意义:
- 在 getter 内部调用
Date.now()、Math.random()或读取非响应式对象(如普通 const 变量) - 返回新对象或数组引用,例如:
() => ({ ...state.obj })或() => state.list.slice()—— 即使内容相同,引用变了,组件就认为数据更新了 - 在 getter 中发起 API 请求或 await 异步操作(getters 必须是同步纯函数)
对带参 getter 做手动缓存
像 tasksByStatus: (state) => (status) => state.tasks.filter(...) 这类写法,Pinia 不会为不同 status 值分别缓存。如果参数组合多、调用频繁,建议封装一层记忆化:
- 用
lodash.memoize:简单可靠,适合参数类型稳定(如字符串、数字) - 用 Map 手动管理:更轻量,适合控制缓存大小或过期策略,例如按参数生成 key,存结果并限制最多缓存 10 组
- 注意:缓存逻辑必须放在 store 外部(如工具函数),不能写在 getter 函数体内,否则每次 getter 调用都会新建缓存实例
与组件配合:只暴露最终语义,不暴露原始计算过程
模板里别写 v-if="store.tasks.filter(...).length",这绕过了所有 getter 缓存。应该在 store 中定义明确语义的 getter:
hasActiveTasks: (state) => state.tasks.some(t => t.status === 'active')visibleTaskCount: (state) => this.searchedTasks.length- 组件中用
storeToRefs解构,直接绑定到模板,既清晰又享受完整缓存链










