Vuex vs Pinia
状态管理该用哪个?
先说结论
在 Vue 3 新项目中,优先选择 Pinia。它是 Vue 官方推荐的状态管理库,API 更贴近 Composition API,TypeScript 类型推导也更自然。
Vuex 并不是“不能用”:Vuex 4 仍适合已经大量使用 Vuex 的 Vue 3 老项目。迁移的收益主要在开发体验和类型安全,不必为了换库而一次性重写整个项目。
Vuex 有什么问题?
- 样板代码较多:State、Getters、Mutations、Actions 和
commit/dispatch通常需要分别声明。 - Mutation 与 Action 的边界容易增加心智负担:Mutation 原则上只负责同步修改,异步逻辑要放在 Action 中;Pinia 的 Action 可以直接包含同步或异步逻辑。
- 模块使用体验偏重:模块通常通过命名空间和字符串路径访问,随着模块增多,重命名和类型约束会变得麻烦。
- TypeScript 使用成本较高:并非不能用 TS,但需要更多显式类型和辅助写法,类型不会像 Pinia 那样自然贯穿 Store。
这些是 Vuex 的使用成本,不代表它的响应式、插件机制或严格模式失效;已有项目继续维护 Vuex 是合理的。
Pinia 强在哪?
Pinia 既支持 Composition API,也支持 Options API:
- API 更直接:Store 由 State、Getters、Actions 组成,没有 Mutations;组件可以直接读取和修改状态,也可以调用 Action。
- TypeScript 友好:从
defineStore推导 State、Getters 和 Actions 的类型,减少字符串路径和手动声明。 - Store 天然拆分:每个 Store 有自己的 id 和依赖边界,按需引入;不需要再维护一棵集中式 modules 树。
- 更适合组合式逻辑:Store 可以使用
ref、computed和普通函数组织复杂业务逻辑。 - 生态能力完整:支持插件、持久化等扩展,并提供 SSR 使用方式。
“体积小于 1KB”不建议作为固定结论:实际产物会受版本、构建方式和依赖压缩影响。比较时应以项目构建后的 bundle 分析为准。
API 怎么对应?
Pinia 取消 Mutations 并不等于“任何地方都随意改状态”。复杂变更仍建议集中到 Action 中,这样更容易复用、测试和追踪;简单表单状态则可以直接赋值。
迁移时注意什么?
- 不要机械地把 Mutation 改成普通函数:先按业务边界拆分 Store,再决定哪些修改保留为直接赋值,哪些收敛到 Action。
- 替换访问方式:
mapState、mapActions、commit、dispatch需要改成 Store 实例的属性访问和方法调用。 - 检查插件与持久化:Vuex 插件、严格模式、持久化插件都要逐项确认 Pinia 的替代方案,不能默认行为完全一致。
- SSR 要隔离请求状态:服务端渲染时应按请求创建 Pinia 实例,避免多个请求共享同一份 Store;脱水和恢复状态时也要校验数据边界。
- 可以渐进迁移:Vuex 和 Pinia 可以在同一个 Vue 应用中共存,但应明确状态归属,避免同一份业务状态被两个 Store 同时维护。
怎么选?
- Vue 3 新项目:优先 Pinia。
- 已有 Vuex 4 项目:如果运行稳定、维护成本可接受,可以继续使用;新功能是否迁移应结合团队规范和改造成本决定。
- 需要渐进迁移:先让新业务使用 Pinia,逐步迁移边界清晰、变更频繁的 Vuex 模块,避免同时维护两套事实来源。
- 状态很少的页面:不一定需要全局状态管理;组件状态用
ref/reactive,跨层传递用provide/inject,通常更简单。
总结
一句话回答:新项目用 Pinia,老项目不必为了“换成 Pinia”而重写;是否迁移取决于类型安全、维护成本和改造收益。

