Pinia
Vue 官方推荐的新一代状态管理库,以直觉、类型安全和轻量为核心设计理念。
Pinia 是 Vue 3 默认状态管理方案,由 Vue 核心团队成员创建。去掉 Vuex 的 mutations、命名空间等繁琐设计,拥抱 Composition API,体积仅约 1.5KB。支持完整 TypeScript 推导、多 Store 独立拆分、HMR 和 DevTools 集成。
Pinia
Vue 官方推荐的新一代状态管理库,以直觉、类型安全和轻量为核心设计理念。
技术简介说明
Pinia 是 Vue.js 生态中的新一代集中式状态管理库,由 Vue 核心团队成员 Eduardo San Martin Morote(posva)创建,同时也是 Vue Router 的作者。Pinia 最初于 2019 年底作为 Vuex 5 的探索原型诞生(项目名 "Pinia" 源自西班牙语中"菠萝" piña 的谐音),随着设计的成熟和社区的广泛认可,最终被 Vue 官方正式采纳为 Vue 3 的默认状态管理方案,取代了 Vuex 在新项目中的地位。
Pinia 的核心价值在于:它既保留了 Vuex 中"单一数据源"(Single Source of Truth)的核心思想,又彻底重构了 API 设计——去掉了 Vuex 中繁琐的 mutations、namespace 模块系统和样板代码,转而拥抱 Vue 3 的 Composition API,实现了完全的 TypeScript 类型推导、模块热更新和多 Store 独立拆分。整个库的体积仅约 1.5KB(gzipped),几乎可以忽略不计,是目前 Vue 生态中性能和开发体验最佳的状态管理方案。
截至 2025-2026 年,Pinia 已发布 v3 大版本(仅支持 Vue 3),在 GitHub 上拥有超过 14.6k Stars,npm 周下载量超过百万,已经成为 Vue 生态中使用最广泛的状态管理库。Pinia 同时得到了 Nuxt 3 的官方集成支持,并与 Sentry、Vue DevTools 等工具深度整合,形成了完善的生态体系。
基本信息
- 官网: https://pinia.vuejs.org
- GitHub: https://github.com/vuejs/pinia
- License: MIT
- 最新版本: v3.0.4(2025 年 11 月发布)
- 主要维护者/公司: Eduardo San Martin Morote(posva),Vue.js 官方团队
快速上手
安装(npm/yarn/pnpm)
# npm
npm install pinia
# yarn
yarn add pinia
# pnpm
pnpm add pinia注意:Pinia v3 仅支持 Vue 3,Vue 2 项目请使用 Pinia v2(
npm install pinia@2)。
基础配置
在 Vue 3 应用的入口文件中安装 Pinia 插件:
// main.ts
import { createApp } from 'vue'
import { createPinia } from 'pinia'
import App from './App.vue'
const app = createApp(App)
const pinia = createPinia()
app.use(pinia)
app.mount('#app')在 Nuxt 3 中,Pinia 已通过 @pinia/nuxt 模块官方集成:
pnpm add @pinia/nuxt// nuxt.config.ts
export default defineNuxtConfig({
modules: ['@pinia/nuxt'],
})最小示例
Pinia 推荐使用 Setup Store(组合式 API)风格定义 Store,这也是 Vue 3 官方推荐的方式:
// stores/counter.ts
import { defineStore } from 'pinia'
import { ref, computed } from 'vue'
export const useCounterStore = defineStore('counter', () => {
// State:响应式状态
const count = ref(0)
// Getters:计算属性
const doubleCount = computed(() => count.value * 2)
// Actions:修改状态的方法
function increment() {
count.value++
}
function reset() {
count.value = 0
}
return { count, doubleCount, increment, reset }
})在组件中使用:
<script setup lang="ts">
import { useCounterStore } from '@/stores/counter'
import { storeToRefs } from 'pinia'
const counterStore = useCounterStore()
// 使用 storeToRefs 解构时保持响应式
const { count, doubleCount } = storeToRefs(counterStore)
const { increment, reset } = counterStore
</script>
<template>
<div>
<p>当前计数:{{ count }}</p>
<p>双倍计数:{{ doubleCount }}</p>
<button @click="increment">+1</button>
<button @click="reset">重置</button>
</div>
</template>也支持传统的 Options Store 风格(类似 Vuex,但无需 mutations):
// stores/counter.ts
import { defineStore } from 'pinia'
export const useCounterStore = defineStore('counter', {
state: () => ({
count: 0,
}),
getters: {
doubleCount: (state) => state.count * 2,
},
actions: {
increment() {
this.count++
},
},
})核心概念与架构
Pinia 的架构围绕三个核心概念展开:
1. Store(仓库)
Store 是 Pinia 的基本单元,每个 Store 通过 defineStore() 定义,返回一个唯一的响应式状态对象。与 Vuex 不同,Pinia 天然支持多 Store 模式——你可以按功能边界定义多个独立的 Store,每个 Store 由打包工具自动进行代码分割,无需手动管理命名空间模块。
2. State(状态)
State 是 Store 中存储的数据,通过 ref() 或 reactive() 定义。Pinia 自动将所有 State 包裹在 Vue 3 的响应式系统中,任何 State 变更都会自动触发依赖组件的重新渲染。
3. Getters(计算属性)
Getters 是 Store 中的计算属性,通过 computed() 定义,用于从 State 派生出新的值。Getters 具有缓存特性,只有当其依赖的 State 发生变化时才会重新计算。
4. Actions(操作)
Actions 是修改 State 的方法。与 Vuex 不同,Pinia 取消了 mutations,Actions 中可以同时包含同步和异步操作,直接在 Action 中修改 State 即可。这大幅简化了代码流程,消除了 Vuex 中"同步 mutation + 异步 action"的二元模式带来的样板代码。
架构流程
组件 → 调用 Store Action → 直接修改 State → 响应式自动更新组件
↑
Getters(计算派生值)
核心特性
-
🧩 直觉化 API:无需学习 mutations、命名空间模块、映射辅助函数等概念,API 设计与 Vue 3 Composition API 完全一致,Vue 开发者可以零学习成本上手。
-
🔒 完整的 TypeScript 支持:所有 Store 提供完整的类型推导,即使在 JavaScript 项目中也能获得自动补全支持,无需手动编写类型声明文件。
-
⚡ 极致轻量(~1.5KB gzipped):相比 Vuex 约 6KB 的体积,Pinia 仅约 1.5KB,几乎不增加打包负担。
-
📦 模块化设计:天然支持多 Store,每个 Store 独立定义、独立代码分割,无需像 Vuex 那样通过
modules和namespaced选项组织代码。 -
🔌 插件系统:提供灵活的插件 API,可以扩展 Store 功能,实现状态持久化、事务管理、错误追踪等高级特性。
-
🛠️ DevTools 集成:与 Vue DevTools 深度集成,支持时间旅行调试(time-travel debugging)、状态快照导入/导出、Store 可视化等功能。
-
🔄 Store 间交叉引用:Store 之间可以直接互相引用,无需像 Vuex 那样通过
rootState或dispatch间接通信,类型安全且直观。 -
🌐 SSR 支持:原生支持服务端渲染(SSR),在 Nuxt 3 中有官方模块集成,支持 SSR 状态序列化与反序列化。
-
🎯 支持 Composition API 和 Options API:同时支持 Setup Store(推荐)和 Options Store 两种定义方式,兼容不同开发偏好。
-
📝 热模块替换(HMR):支持 Store 的热更新,开发时修改 Store 代码无需刷新页面。
生态图
Pinia 的生态在 2025-2026 年已相当完善:
| 生态项目 | 说明 |
|---|---|
| Pinia | 核心库,Vue 3 官方状态管理方案 |
| @pinia/nuxt | Nuxt 3 官方 Pinia 集成模块 |
| Pinia Colada | 官方智能数据获取层,提供缓存、请求去重、异步状态管理(类似 TanStack Query) |
| pinia-plugin-persistedstate | 最流行的持久化插件,支持 localStorage/sessionStorage/自定义存储 |
| pinia-orm | 基于 Pinia 的 ORM 库,提供类 Eloquent 的模型操作 API |
| Pinia Shared | 跨浏览器标签页状态共享插件 |
| feathers-pinia | 基于 Pinia 的 FeathersJS 实时数据集成 |
| Sentry Pinia 插件 | Sentry 错误监控框架中的 Pinia 状态追踪支持 |
| pinia-cursed | Pinia 状态可视化工具 |
适用场景
-
Vue 3 新项目:Pinia 是 Vue 官方推荐的默认状态管理方案,所有新的 Vue 3 项目应优先选择 Pinia。
-
需要 TypeScript 类型安全的项目:Pinia 提供完整的类型推导,是中大型 TypeScript 项目的最佳选择。
-
中大型复杂应用:多 Store 架构天然支持功能模块化,适合电商、CMS、SaaS 等业务复杂度较高的应用。
-
SSR / Nuxt 3 应用:Pinia 在 Nuxt 3 中有官方集成,状态序列化和水合(hydration)开箱即用。
-
需要从 Vuex 迁移的项目:Pinia 与 Vuex 可以共存于同一项目中,官方提供了详细的迁移指南,支持渐进式迁移。
-
需要数据获取和缓存的场景:配合 Pinia Colada,可以实现类 TanStack Query 的声明式数据获取、缓存和失效管理。
-
微前端架构:多个独立的 Store 适合微前端中各子应用独立管理自身状态,避免全局 Store 膨胀。
开发与工程化
与 Vue DevTools 集成
Pinia 自动注册到 Vue DevTools(v7+),提供:
- Store 状态可视化查看
- 时间旅行调试(修改 State 并回溯)
- 状态快照导出/导入
- Action 调用追踪
状态持久化
使用 pinia-plugin-persistedstate 实现跨页面/会话的状态持久化:
// stores/user.ts
import { defineStore } from 'pinia'
import { ref } from 'vue'
export const useUserStore = defineStore('user', () => {
const token = ref('')
const userInfo = ref(null)
return { token, userInfo }
}, {
persist: {
storage: localStorage,
paths: ['token'], // 只持久化 token 字段
},
})// main.ts
import { createPinia } from 'pinia'
import piniaPluginPersistedstate from 'pinia-plugin-persistedstate'
const pinia = createPinia()
pinia.use(piniaPluginPersistedstate)测试支持
Pinia 提供了完善的测试工具,可以在测试中轻松 mock Store:
// counter.test.ts
import { setActivePinia, createPinia } from 'pinia'
import { useCounterStore } from '@/stores/counter'
import { describe, it, expect, beforeEach } from 'vitest'
describe('Counter Store', () => {
beforeEach(() => {
setActivePinia(createPinia())
})
it('increments count', () => {
const store = useCounterStore()
expect(store.count).toBe(0)
store.increment()
expect(store.count).toBe(1)
})
it('computes doubleCount', () => {
const store = useCounterStore()
store.count = 5
expect(store.doubleCount).toBe(10)
})
})与 Vue Router 集成
Pinia 可以与 Vue Router 深度集成,实现路由级状态管理和导航守卫:
// stores/auth.ts
import { defineStore } from 'pinia'
import { ref } from 'vue'
export const useAuthStore = defineStore('auth', () => {
const isAuthenticated = ref(false)
const user = ref(null)
async function login(credentials: { email: string; password: string }) {
const response = await fetch('/api/login', {
method: 'POST',
body: JSON.stringify(credentials),
})
if (response.ok) {
const data = await response.json()
user.value = data.user
isAuthenticated.value = true
}
}
function logout() {
user.value = null
isAuthenticated.value = false
}
return { isAuthenticated, user, login, logout }
})// router/index.ts
router.beforeEach((to, from) => {
const authStore = useAuthStore()
if (to.meta.requiresAuth && !authStore.isAuthenticated) {
return { name: 'Login' }
}
})性能与安全
性能特性
- 极小体积:~1.5KB gzipped,支持 tree-shaking,未使用的功能不会被打包
- 响应式高效:基于 Vue 3 的
reactive()/ref()实现,使用 Proxy 代理,性能优于 Vue 2 的Object.defineProperty - 多 Store 代码分割:每个 Store 可被打包工具独立分割,实现按需加载
- Getters 缓存:计算属性自动缓存,避免不必要的重复计算
安全考量
- 状态不在 URL 中暴露:Pinia Store 状态存储在内存中,不会自动暴露在 URL 参数中
- SSR 状态序列化:在 SSR 场景中使用
@pinia/nuxt的状态序列化机制,注意不要在 State 中存储敏感信息(如密码、API Key),因为这些数据会通过<script>标签传递到客户端 - XSS 防护:Pinia 本身不会引入 XSS 风险,但仍需注意从 Store 中取出的数据在渲染时的转义处理
- 插件安全:第三方插件可能引入安全风险,建议仅使用官方推荐或社区广泛验证的插件
技术对比
| 特性 | Pinia | Vuex 4 | Redux | MobX | Zustand |
|---|---|---|---|---|---|
| 适用框架 | Vue 3 | Vue 3 | React/通用 | 框架无关 | React/通用 |
| 包体积 | ~1.5KB | ~6KB | ~7KB | ~16KB | ~1KB |
| TypeScript 支持 | ✅ 完整推导 | ⚠️ 需手动声明 | ⚠️ 需样板代码 | ✅ 良好 | ✅ 良好 |
| Composition API | ✅ 原生支持 | ❌ 不支持 | ❌ 不支持 | ⚠️ 部分支持 | ❌ 不支持 |
| Mutations | ❌ 已移除 | ✅ 必须使用 | ❌ 无 | ❌ 无 | ❌ 无 |
| DevTools 集成 | ✅ 完整 | ✅ 完整 | ✅ 完整 | ✅ 完整 | ✅ 基本 |
| SSR 支持 | ✅ 官方 Nuxt 模块 | ✅ 需手动配置 | ✅ 需手动配置 | ⚠️ 有限 | ⚠️ 有限 |
| 模块系统 | 多 Store 天然模块化 | modules + namespaced | slices | 无原生模块 | 多 Store |
| 插件生态 | 丰富且活跃 | 稳定但不再扩展 | 最丰富 | 丰富 | 丰富 |
| Vue 官方推荐 | ✅ 是(当前默认) | ❌ 否(维护模式) | ❌ 否 | ❌ 否 | ❌ 否 |
| 学习曲线 | 低 | 中高 | 高 | 中 | 低 |
最佳实践
1. 优先使用 Setup Store 风格
Setup Store 使用 Composition API 语法,与 Vue 3 组件风格一致,逻辑更清晰:
// ✅ 推荐:Setup Store
export const useTodoStore = defineStore('todo', () => {
const todos = ref<Todo[]>([])
const completedTodos = computed(() =>
todos.value.filter(t => t.completed)
)
async function fetchTodos() {
todos.value = await api.getTodos()
}
return { todos, completedTodos, fetchTodos }
})2. 按功能边界拆分 Store
不要把所有状态放在一个 Store 中,按业务功能拆分:
// ✅ 好:按功能拆分
useAuthStore() // 认证相关
useCartStore() // 购物车
useNotificationStore() // 通知
// ❌ 避免:单一大 Store
useAppStore() // 包含所有状态,难以维护3. 合理使用 Getters 缓存复杂计算
// ✅ Getters 自动缓存,适合复杂计算
const expensiveStats = computed(() => {
return items.value.reduce((acc, item) => {
// 复杂计算逻辑
return acc + item.value * item.weight
}, 0)
})
// ❌ 避免在模板中直接进行复杂计算4. Actions 中使用 this 访问 Store(Options Store)或闭包引用(Setup Store)
// Setup Store 中通过闭包访问其他状态和 actions
export const useOrderStore = defineStore('order', () => {
const items = ref([])
const total = computed(() => items.value.reduce((sum, i) => sum + i.price, 0))
async function checkout() {
// 直接访问 items 和 total
await api.createOrder({ items: items.value, total: total.value })
}
return { items, total, checkout }
})5. 使用 storeToRefs 解构保持响应式
// ✅ 正确解构方式
const { count, name } = storeToRefs(counterStore)
// ❌ 错误:直接解构会丢失响应式
const { count, name } = counterStore6. 合理使用 Pinia Colada 处理数据获取
对于需要缓存和去重的 API 请求,使用 Pinia Colada:
import { useQuery } from '@pinia/colada'
const { data, status, error } = useQuery({
key: ['user', userId],
query: () => fetchUser(userId),
})技术局限与边界
-
仅支持 Vue 3(v3 版本):Pinia v3 仅支持 Vue 3,Vue 2 项目必须使用 Pinia v2 或 Vuex 3。
-
不支持 React / 其他框架:Pinia 是 Vue 专属库,无法在 React、Svelte 等其他框架中使用(与 Redux、Zustand 等跨框架方案不同)。
-
无内置数据获取/缓存层:Pinia 核心仅处理状态管理,不内置请求缓存、去重、轮询等数据获取功能,需要配合 Pinia Colada 或 VueUse 实现。
-
无内置持久化:状态持久化需要第三方插件(如
pinia-plugin-persistedstate),不像某些方案开箱即用。 -
Store 间循环引用需注意:虽然 Store 间可以互相引用,但循环引用会导致运行时错误,需要通过延迟引用或依赖注入解决。
-
DevTools 依赖 v7+:Pinia v3 要求 Vue DevTools v7 及以上版本,不再支持旧版 DevTools。
-
SSR 状态序列化限制:State 中不能包含函数、
undefined、Symbol等无法 JSON 序列化的值,SSR 时需要注意。
学习资源
官方资源
社区资源
- Pinia Colada 官方文档 — 数据获取层
- pinia-plugin-persistedstate 文档 — 持久化插件
- Pinia ORM 文档 — ORM 扩展
- Vue School: Pinia 教程 — 视频课程
- Vue Mastery: Pinia 课程 — 视频课程
中文资源
- Pinia 中文文档 — 官方中文翻译
- Vue 3 + Pinia 完整指南(2025)
- 掘金 Pinia 相关文章 — 大量中文实战教程
2026 年现状
截至 2026 年,Pinia 的地位已经非常稳固:
-
Vue 官方唯一推荐:Pinia 是 Vue 3 和 Nuxt 3 的官方默认状态管理方案,Vue 官方脚手架
create-vue默认集成 Pinia。Vuex 已被明确标记为维护模式,不再有新功能开发。 -
Pinia 3 稳定成熟:v3.0.4 是当前最新稳定版,作为"boring release"清理了旧 API,仅支持 Vue 3,迁移成本低。社区已完成从 v2 到 v3 的大规模迁移。
-
Pinia Colada 快速发展:作为 Pinia 的官方数据获取层,Pinia Colada 在 2025-2026 年快速成熟,提供了类 TanStack Query 的缓存、去重、失效管理能力,进一步完善了 Pinia 的数据管理版图。
-
生态系统繁荣:
pinia-plugin-persistedstate、pinia-orm等插件持续活跃更新,Sentry、Vitest 等工具链全面支持 Pinia。 -
社区全面转向 Pinia:2025-2026 年的 Vue 技术文章、教程、面试题几乎都以 Pinia 为主,Vuex 相关内容逐渐减少。新项目选择 Pinia 已成为社区共识。
-
企业级广泛应用:Pinia 已被大量企业级项目采用,包括电商、金融、CMS、SaaS 等领域,其稳定性和可维护性得到充分验证。
-
与 Vue 核心同步演进:Pinia 跟随 Vue 3 的核心版本同步更新,确保与最新的 Vue 特性(如 Suspense、Signals 提案等)保持兼容。