Pinia 核心:state、getters 与 actions 数据流
定义 store 之后,日常打交道的就是三块:state 放什么、getters 算什么、actions 里写什么。
这篇把 单向数据流在 Pinia 里的落点 讲清楚:什么时候直接改 state、什么时候走 action、getter 和计算属性怎么选。
state:唯一真相源,但要控制粒度
state 是 store 里的响应式数据,原则很简单:
- 可序列化、可恢复的业务事实 适合进 state(列表、当前用户 id、分页游标等);
- 派生展示 尽量别复制一份进 state(除非有性能或缓存需求)。
颗粒度上:
- 一个 store 对应 一个业务子域(用户会话、订单草稿)往往比「整个应用一个巨型 store」好测、好拆。
getters:Store 层的「计算属性」
getters 类似组件里的 computed:
- 依赖 state / 其它 getter,自动缓存;
- 适合 列表过滤、汇总、可见性判断。
和组件里再写 computed 的分工可以记:
- 跨多个组件重复出现的派生逻辑,提到 getter;
- 只服务一个页面布局 的派生,留在组件即可。
若 getter 需要参数,可以返回一个函数(注意:这会变成「按调用创建」,缓存行为与无参 getter 不同,要心里有数)。
actions:异步与副作用的默认入口
actions 里常见放:
- 请求后端、读写
localStorage、调其它 store; - 一段 有业务语义的流程(登录、下单、刷新列表)。
为什么要通过 action 而不是在组件里直接改 state?
- 调用栈更清晰:日后排查「谁改了这份数据」时好找;
- 同一入口做校验与错误处理,避免散落各处。
Pinia 里 可以直接在 action 里改 this.xxx,也可以封装成小函数,团队统一风格即可。
数据流怎么走:一个最小闭环
- 组件
useStore(); - 模板或逻辑里读 state / getter;
- 用户操作触发 action;
- action 更新 state(或请求后再更新);
- 响应式链路刷新 UI。
这和 Redux「dispatch → reducer」不完全一样,但 「读通过 getter、写尽量经 action」 的习惯仍然值得保留。
常见坑:解构丢失响应式
在组件里如果这样写:
const { count } = useCounterStore()
可能丢掉响应式。习惯用法是:
- 用
storeToRefs解构 state/getter; - 或者始终用
store.count点取。
这一点写错时 bug 很隐蔽,值得记在团队规范里。
小结:三块各司其职
- state 管事实,控制域边界;
- getters 管派生,减少重复计算;
- actions 管流程与副作用,是协作与排障的主入口。
下一篇讲 setup 风格 store 与大项目 拆分策略。