Pinia logo

Pinia

Vue 官方推荐的新一代状态管理库,以直觉、类型安全和轻量为核心设计理念。

精选工具状态管理Vue官方推荐Composition API

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 中繁琐的 mutationsnamespace 模块系统和样板代码,转而拥抱 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 等工具深度整合,形成了完善的生态体系。

基本信息

快速上手

安装(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(计算派生值)

核心特性

  1. 🧩 直觉化 API:无需学习 mutations、命名空间模块、映射辅助函数等概念,API 设计与 Vue 3 Composition API 完全一致,Vue 开发者可以零学习成本上手。

  2. 🔒 完整的 TypeScript 支持:所有 Store 提供完整的类型推导,即使在 JavaScript 项目中也能获得自动补全支持,无需手动编写类型声明文件。

  3. ⚡ 极致轻量(~1.5KB gzipped):相比 Vuex 约 6KB 的体积,Pinia 仅约 1.5KB,几乎不增加打包负担。

  4. 📦 模块化设计:天然支持多 Store,每个 Store 独立定义、独立代码分割,无需像 Vuex 那样通过 modulesnamespaced 选项组织代码。

  5. 🔌 插件系统:提供灵活的插件 API,可以扩展 Store 功能,实现状态持久化、事务管理、错误追踪等高级特性。

  6. 🛠️ DevTools 集成:与 Vue DevTools 深度集成,支持时间旅行调试(time-travel debugging)、状态快照导入/导出、Store 可视化等功能。

  7. 🔄 Store 间交叉引用:Store 之间可以直接互相引用,无需像 Vuex 那样通过 rootStatedispatch 间接通信,类型安全且直观。

  8. 🌐 SSR 支持:原生支持服务端渲染(SSR),在 Nuxt 3 中有官方模块集成,支持 SSR 状态序列化与反序列化。

  9. 🎯 支持 Composition API 和 Options API:同时支持 Setup Store(推荐)和 Options Store 两种定义方式,兼容不同开发偏好。

  10. 📝 热模块替换(HMR):支持 Store 的热更新,开发时修改 Store 代码无需刷新页面。

生态图

Pinia 的生态在 2025-2026 年已相当完善:

生态项目说明
Pinia核心库,Vue 3 官方状态管理方案
@pinia/nuxtNuxt 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-cursedPinia 状态可视化工具

适用场景

  1. Vue 3 新项目:Pinia 是 Vue 官方推荐的默认状态管理方案,所有新的 Vue 3 项目应优先选择 Pinia。

  2. 需要 TypeScript 类型安全的项目:Pinia 提供完整的类型推导,是中大型 TypeScript 项目的最佳选择。

  3. 中大型复杂应用:多 Store 架构天然支持功能模块化,适合电商、CMS、SaaS 等业务复杂度较高的应用。

  4. SSR / Nuxt 3 应用:Pinia 在 Nuxt 3 中有官方集成,状态序列化和水合(hydration)开箱即用。

  5. 需要从 Vuex 迁移的项目:Pinia 与 Vuex 可以共存于同一项目中,官方提供了详细的迁移指南,支持渐进式迁移。

  6. 需要数据获取和缓存的场景:配合 Pinia Colada,可以实现类 TanStack Query 的声明式数据获取、缓存和失效管理。

  7. 微前端架构:多个独立的 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),因为这些数据会通过 &lt;script&gt; 标签传递到客户端
  • XSS 防护:Pinia 本身不会引入 XSS 风险,但仍需注意从 Store 中取出的数据在渲染时的转义处理
  • 插件安全:第三方插件可能引入安全风险,建议仅使用官方推荐或社区广泛验证的插件

技术对比

特性PiniaVuex 4ReduxMobXZustand
适用框架Vue 3Vue 3React/通用框架无关React/通用
包体积~1.5KB~6KB~7KB~16KB~1KB
TypeScript 支持✅ 完整推导⚠️ 需手动声明⚠️ 需样板代码✅ 良好✅ 良好
Composition API✅ 原生支持❌ 不支持❌ 不支持⚠️ 部分支持❌ 不支持
Mutations❌ 已移除✅ 必须使用❌ 无❌ 无❌ 无
DevTools 集成✅ 完整✅ 完整✅ 完整✅ 完整✅ 基本
SSR 支持✅ 官方 Nuxt 模块✅ 需手动配置✅ 需手动配置⚠️ 有限⚠️ 有限
模块系统多 Store 天然模块化modules + namespacedslices无原生模块多 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 } = counterStore

6. 合理使用 Pinia Colada 处理数据获取

对于需要缓存和去重的 API 请求,使用 Pinia Colada:

import { useQuery } from '@pinia/colada'
 
const { data, status, error } = useQuery({
  key: ['user', userId],
  query: () => fetchUser(userId),
})

技术局限与边界

  1. 仅支持 Vue 3(v3 版本):Pinia v3 仅支持 Vue 3,Vue 2 项目必须使用 Pinia v2 或 Vuex 3。

  2. 不支持 React / 其他框架:Pinia 是 Vue 专属库,无法在 React、Svelte 等其他框架中使用(与 Redux、Zustand 等跨框架方案不同)。

  3. 无内置数据获取/缓存层:Pinia 核心仅处理状态管理,不内置请求缓存、去重、轮询等数据获取功能,需要配合 Pinia Colada 或 VueUse 实现。

  4. 无内置持久化:状态持久化需要第三方插件(如 pinia-plugin-persistedstate),不像某些方案开箱即用。

  5. Store 间循环引用需注意:虽然 Store 间可以互相引用,但循环引用会导致运行时错误,需要通过延迟引用或依赖注入解决。

  6. DevTools 依赖 v7+:Pinia v3 要求 Vue DevTools v7 及以上版本,不再支持旧版 DevTools。

  7. SSR 状态序列化限制:State 中不能包含函数、undefinedSymbol 等无法 JSON 序列化的值,SSR 时需要注意。

学习资源

官方资源

社区资源

中文资源

2026 年现状

截至 2026 年,Pinia 的地位已经非常稳固:

  1. Vue 官方唯一推荐:Pinia 是 Vue 3 和 Nuxt 3 的官方默认状态管理方案,Vue 官方脚手架 create-vue 默认集成 Pinia。Vuex 已被明确标记为维护模式,不再有新功能开发。

  2. Pinia 3 稳定成熟:v3.0.4 是当前最新稳定版,作为"boring release"清理了旧 API,仅支持 Vue 3,迁移成本低。社区已完成从 v2 到 v3 的大规模迁移。

  3. Pinia Colada 快速发展:作为 Pinia 的官方数据获取层,Pinia Colada 在 2025-2026 年快速成熟,提供了类 TanStack Query 的缓存、去重、失效管理能力,进一步完善了 Pinia 的数据管理版图。

  4. 生态系统繁荣pinia-plugin-persistedstatepinia-orm 等插件持续活跃更新,Sentry、Vitest 等工具链全面支持 Pinia。

  5. 社区全面转向 Pinia:2025-2026 年的 Vue 技术文章、教程、面试题几乎都以 Pinia 为主,Vuex 相关内容逐渐减少。新项目选择 Pinia 已成为社区共识。

  6. 企业级广泛应用:Pinia 已被大量企业级项目采用,包括电商、金融、CMS、SaaS 等领域,其稳定性和可维护性得到充分验证。

  7. 与 Vue 核心同步演进:Pinia 跟随 Vue 3 的核心版本同步更新,确保与最新的 Vue 特性(如 Suspense、Signals 提案等)保持兼容。