Pinia 简介 #

什么是 Pinia? #

Pinia(发音为 /piːnjʌ/,类似英语中的 “peenya”)是 Vue.js 的专属状态管理库,它允许你跨组件或页面共享状态。Pinia 由 Vue 核心团队成员 Eduardo San Martin Morote 开发,现已成为 Vue 官方推荐的状态管理方案。

为什么叫 Pinia? #

Pinia 在西班牙语中意为"菠萝"。菠萝单独看起来是一个独立的水果,但实际上它是由许多小浆果聚合成的一个整体。这恰好象征了 Pinia 的设计理念:每个 Store 都是独立的,但它们共同组成了完整的状态管理系统。

Pinia 的特点 #

1. 简洁的 API #

Pinia 的 API 非常简洁,只有三个核心概念:

text
Pinia 核心
├── State ────── 状态数据
├── Getters ──── 计算属性
└── Actions ──── 方法(同步/异步)

2. 完整的 TypeScript 支持 #

Pinia 从设计之初就考虑了 TypeScript,提供开箱即用的类型推断:

ts
import { defineStore } from 'pinia'

export const useUserStore = defineStore('user', {
  state: () => ({
    name: 'John',
    age: 25
  }),
  getters: {
    isAdult: (state) => state.age >= 18
  },
  actions: {
    updateAge(newAge: number) {
      this.age = newAge
    }
  }
})

3. 无需 mutations #

与 Vuex 不同,Pinia 移除了 mutations 的概念:

ts
// Vuex 方式
mutations: {
  increment(state) {
    state.count++
  }
}

// Pinia 方式 - 直接修改或使用 actions
actions: {
  increment() {
    this.count++  // 直接修改
  }
}

4. 天然模块化 #

每个 Store 都是独立的,无需像 Vuex 那样手动配置 modules:

ts
// stores/user.ts
export const useUserStore = defineStore('user', { /* ... */ })

// stores/cart.ts
export const useCartStore = defineStore('cart', { /* ... */ })

// stores/product.ts
export const useProductStore = defineStore('product', { /* ... */ })

5. 支持多个 Store 实例 #

Pinia 支持在同一应用中创建多个 Pinia 实例,适用于测试或微前端场景:

ts
import { createPinia } from 'pinia'

const pinia1 = createPinia()
const pinia2 = createPinia()

Pinia vs Vuex #

特性 Pinia Vuex
API 复杂度 简单,只有 state/getters/actions 复杂,有 state/getters/mutations/actions
TypeScript 原生支持,完整类型推断 需要额外配置
模块化 自动,每个 store 独立 需要手动配置 modules
Mutations 必须通过 mutations 修改状态
代码分割 容易 需要额外配置
DevTools 完整支持 完整支持
包体积 ~1KB ~3KB
学习曲线

什么时候使用 Pinia? #

适合使用 Pinia 的场景 #

  1. 跨组件共享状态:多个组件需要访问同一状态
  2. 复杂应用状态:应用有复杂的状态逻辑
  3. 需要状态持久化:需要将状态保存到本地存储
  4. 大型应用:需要模块化管理状态
  5. TypeScript 项目:需要完整的类型支持

不需要状态管理的场景 #

  1. 简单应用:组件间不需要共享状态
  2. 父子组件通信:使用 props/emit 即可
  3. 临时状态:使用组件内部 state 即可

Pinia 的设计理念 #

单一职责 #

每个 Store 只负责一个领域:

ts
// 用户相关状态
export const useUserStore = defineStore('user', { /* ... */ })

// 购物车相关状态
export const useCartStore = defineStore('cart', { /* ... */ })

// 产品相关状态
export const useProductStore = defineStore('product', { /* ... */ })

扁平化结构 #

Pinia 采用扁平化的 Store 结构,避免了 Vuex 的嵌套模块问题:

text
Vuex 结构(嵌套)
├── modules
│   ├── user
│   │   └── modules
│   │       └── profile
│   └── cart

Pinia 结构(扁平)
├── stores
│   ├── user.ts
│   ├── profile.ts
│   └── cart.ts

组合式设计 #

Pinia 支持两种定义 Store 的方式:

ts
// Options API 风格
export const useCounterStore = defineStore('counter', {
  state: () => ({ count: 0 }),
  getters: {
    double: (state) => state.count * 2
  },
  actions: {
    increment() { this.count++ }
  }
})

// Setup 风格(组合式 API)
export const useCounterStore = defineStore('counter', () => {
  const count = ref(0)
  const double = computed(() => count.value * 2)
  function increment() { count.value++ }
  return { count, double, increment }
})

Pinia 生态系统 #

text
Pinia 生态系统
├── pinia ──────────────────── 核心库
├── pinia-plugin-persistedstate ─ 状态持久化插件
├── @pinia/nuxt ────────────── Nuxt.js 集成
├── @pinia/testing ─────────── 测试工具
└── Vue DevTools ───────────── 调试支持

下一步 #

现在你已经了解了 Pinia 的基本概念,接下来让我们学习如何安装和配置 Pinia。

最后更新:2026-03-28