Pinia 核心:state、getters 与 actions 数据流

定义 store 之后,日常打交道的就是三块:state 放什么、getters 算什么、actions 里写什么
这篇把 单向数据流在 Pinia 里的落点 讲清楚:什么时候直接改 state、什么时候走 action、getter 和计算属性怎么选

state 是 store 里的响应式数据,原则很简单:

  • 可序列化、可恢复的业务事实 适合进 state(列表、当前用户 id、分页游标等);
  • 派生展示 尽量别复制一份进 state(除非有性能或缓存需求)。

颗粒度上:

  • 一个 store 对应 一个业务子域(用户会话、订单草稿)往往比「整个应用一个巨型 store」好测、好拆。

getters 类似组件里的 computed

  • 依赖 state / 其它 getter,自动缓存;
  • 适合 列表过滤、汇总、可见性判断

和组件里再写 computed 的分工可以记:

  • 跨多个组件重复出现的派生逻辑,提到 getter;
  • 只服务一个页面布局 的派生,留在组件即可。

若 getter 需要参数,可以返回一个函数(注意:这会变成「按调用创建」,缓存行为与无参 getter 不同,要心里有数)。

actions 里常见放:

  • 请求后端、读写 localStorage、调其它 store;
  • 一段 有业务语义的流程(登录、下单、刷新列表)。

为什么要通过 action 而不是在组件里直接改 state?

  • 调用栈更清晰:日后排查「谁改了这份数据」时好找;
  • 同一入口做校验与错误处理,避免散落各处。

Pinia 里 可以直接在 action 里改 this.xxx,也可以封装成小函数,团队统一风格即可。

  1. 组件 useStore()
  2. 模板或逻辑里读 state / getter
  3. 用户操作触发 action
  4. action 更新 state(或请求后再更新);
  5. 响应式链路刷新 UI。

这和 Redux「dispatch → reducer」不完全一样,但 「读通过 getter、写尽量经 action」 的习惯仍然值得保留。

在组件里如果这样写:

  • const { count } = useCounterStore()

可能丢掉响应式。习惯用法是:

  • storeToRefs 解构 state/getter;
  • 或者始终用 store.count 点取。

这一点写错时 bug 很隐蔽,值得记在团队规范里。

  • state 管事实,控制域边界;
  • getters 管派生,减少重复计算;
  • actions 管流程与副作用,是协作与排障的主入口。

下一篇讲 setup 风格 store 与大项目 拆分策略