🍍 Vuex → Pinia

一句话定性

Vue 生态的状态管理走了一条独立的路:VuexRedux 的单向数据流”翻译”成 Vue 风味(mutation/action + 响应式)。但当 Vue 3 + Composition API 改变了一切之后,Vuex 的设计变得”格格不入”——于是 Pinia 取而代之,成为 Vue 3 的官方推荐。这是一个”框架范式升级,倒逼状态库重写”的经典案例。


一、它是什么 & 出现的时代

  • Vuex(2015 起):Vue 官方的状态管理库,诞生于 2013-2018 SPA时代。它借鉴 Redux/Flux 的单向数据流思想,但结合了 Vue 的响应式系统。
  • Pinia(2019 起,由 Vue 核心成员 Eduardo San Martin Morote 开发):面向 Vue 3 设计,已成为 Vue 官方推荐的状态管理方案,正式取代 Vuex

名字趣闻

Pinia 取自西班牙语 “piña”(菠萝)。菠萝由许多小花聚成一个整体,隐喻”一组各自独立的 store 组成应用状态”。


二、为什么会出现(解决上一代什么痛点)

Vuex 为什么出现

Redux 同源的动机:Vue 组件化后的跨组件状态共享难题(见 状态管理演进史)。Vuex 给 Vue 一个”官方答案”,带着 Vue 自己的响应式血统。

Pinia 为什么取代 Vuex

Vue 3 + Composition API 让 Vuex"过时"了

Vue 3 引入 Composition API(setup / ref / reactive),整个 Vue 的写法范式变了。在这个新世界里,Vuex 暴露出一堆毛病:

  1. mutation 是多余的仪式:Vuex 强制 state → mutation(同步改)→ action(异步)→ dispatch/commit,这套”为了改值要分两步”的繁文缛节,在 Composition API 时代显得啰嗦又过时(和 Redux 样板诟病同源)。
  2. TypeScript 支持差:Vuex 4 对 TS 的类型推导很别扭,而 2018-2023 工程化时代里 TS 已是刚需。
  3. 模块(modules)设计笨重:命名空间、嵌套模块的写法繁琐易错。
  4. 不契合 Composition API:Vuex 的 API 风格是”配置对象式”的,和 setup() 里函数式的写法割裂。

三、核心机制 & 为什么流行

Vuex 的核心机制

 Component ──commit──► Mutation(同步,唯一能改 state 的地方)──► State(响应式)
      │                                                          │
      └──dispatch──► Action(可异步)──commit──► Mutation         │
      ▲                                                          │
      └────────────────── state 变,组件自动更新(响应式) ─────────┘
  • state:响应式的单一状态树。
  • mutation:唯一能同步修改 state 的地方(对应 Redux reducer 的”显式变更”约束)。
  • action:处理异步,内部再 commit mutation。
  • getter:派生状态(类似 computed)。

Pinia 的核心机制(为什么更好)

Pinia 做减法 + 拥抱 Composition API

  1. 去掉 mutation:直接在 action 里(甚至组件里)修改 state,少一层概念——这是对 Vuex 最大的简化。
  2. 两种写法,Composition 风格优先:可以像写 setup() 一样用 ref/computed/function 定义 store,与 Vue 3 心智完全统一。
  3. 一流的 TypeScript 支持:类型自动推导,无需手写复杂泛型。
  4. 扁平的多 store:不再有嵌套 modules,每个 store 独立、可按需引入,天然 code-splitting 友好。
  5. 更轻量,API 更小,DevTools 支持依旧完善。
// Pinia:像写 Composition API 一样自然
export const useCart = defineStore('cart', () => {
  const items = ref([])                      // state
  const total = computed(() => items.value.length) // getter
  function add(x) { items.value.push(x) }    // action,直接改,无 mutation
  return { items, total, add }
})

四、带来的新问题 / 副作用

Warning

  1. 迁移成本:存量 Vuex 项目迁到 Pinia 需要改写,大型项目有工作量(虽然官方提供了迁移指南)。
  2. “两种写法”带来选择困惑:Pinia 同时支持 Options 风格和 Composition 风格,新手会纠结用哪种。
  3. 去掉 mutation 的取舍:少了一层约束,理论上”哪里都能改 state”,对超大团队的强约束略弱于 Vuex(但 Pinia 在 DevTools 里仍能追踪变更)。

五、现状 / 演化

  • Pinia 已是 Vue 3 的事实标准和官方推荐,Vuex 进入维护模式(不再是新项目首选)。
  • 它的演进完美呼应了 钟摆:从 Vuex 的”严格 mutation 约束”摆向 Pinia 的”更轻、更直接”——与 ReduxZustand 在 React 侧的”去样板”趋势遥相呼应。

六、对后续技术的影响(因果链)

 [[Vue]] 组件化 ──► 跨组件状态共享难题
                       │
                       ▼
   借鉴 [[Redux]]/Flux 单向思想 + Vue 响应式
                       │
                       ▼
                 Vuex(2015)── mutation/action/getter
                       │
                       │  Vue 3 发布 + Composition API 改变范式
                       │  (mutation 多余 / TS 差 / modules 笨重)
                       ▼
                 Pinia(2019→,官方推荐)
                       │
   ┌───────────────────┼───────────────────────┐
   ▼                   ▼                       ▼
 去掉 mutation      Composition 风格优先      一流 TS 支持
   │                   │                       │
   ▼                   ▼                       ▼
 更少概念           与 Vue 3 心智统一         扁平多 store
   │
   ▼
 呼应整体"去样板"趋势(与 React 侧 Redux→[[Zustand]] 同频)

历史地位

Vuex→Pinia 的更替是”框架范式升级倒逼工具重写”的范本:不是 Vuex 写错了,而是 Vue 3 的 Composition API 把游戏规则变了,旧工具不再合身。Pinia 通过”做减法 + 拥抱新范式”成为官方答案,也证明了状态管理钟摆”朝极简、朝响应式自然写法”摆动的大趋势——这一点,与 ReduxMobXZustand 共同构成了 状态管理演进史的完整图景。


🔗 相关:状态管理演进史 | Redux | MobX | Zustand | Vue | 2013-2018 SPA时代 | 2018-2023 工程化时代