Vue3 状态管理库 Pinia 完整教程

21 阅读2分钟

你想系统学习 Vue3 官方推荐的状态管理库 Pinia,我会从核心概念、基础使用、模块化、异步操作到实战技巧,用最简单易懂的方式教你完全掌握。

一、核心概念

Pinia 是 Vue 官方新一代状态管理库,替代 Vuex,专为 Vue3 设计,同时兼容 Vue2,核心优势:

  • 语法简洁,无需 mutation(只有 state、getters、actions)
  • 天然支持 TypeScript
  • 模块化设计,无需嵌套模块
  • 体积更小,性能更高
  • 支持热更新、插件扩展

二、快速上手(步骤)

1. 安装 Pinia

# npm
npm install pinia

# yarn
yarn add pinia

# pnpm
pnpm add pinia

2. 在 main.js 全局注册

import { createApp } from 'vue'
import App from './App.vue'
// 引入 Pinia
import { createPinia } from 'pinia'

const app = createApp(App)
// 挂载 Pinia
app.use(createPinia())
app.mount('#app')

三、定义 Store(核心)

Store 是存储状态和业务逻辑的容器,推荐按功能模块化拆分(如 user、cart、setting)。

1. 创建 Store 示例

src/stores/ 目录下新建文件(如 user.js):

// src/stores/user.js
import { defineStore } from 'pinia'

// 第一个参数:store 唯一 ID(必须唯一)
// 第二个参数:配置对象
export const useUserStore = defineStore('user', {
  // 1. 状态:存储数据(类似 data)
  state: () => ({
    name: '张三',
    age: 20,
    token: ''
  }),

  // 2. 计算属性:派生状态(类似 computed,有缓存)
  getters: {
    // 自动接收 state 作为参数
    doubleAge: (state) => state.age * 2,
    // 也可以使用 this 访问整个 store
    getName: function() {
      return `我的名字:${this.name}`
    }
  },

  // 3. 方法:修改状态、异步请求(类似 methods)
  actions: {
    // 同步修改
    updateName(newName) {
      this.name = newName
    },
    // 异步修改(支持 async/await)
    async login(account, pwd) {
      // 模拟接口请求
      const res = await new Promise(resolve => {
        setTimeout(() => resolve({ token: 'abcd-1234' }), 1000)
      })
      this.token = res.token
      this.name = account
    }
  }
})

四、组件中使用 Store

1. 基础使用(读取/修改状态)

<template>
  <div>
    <p>姓名:{{ userStore.name }}</p>
    <p>年龄:{{ userStore.age }}</p>
    <p>双倍年龄:{{ userStore.doubleAge }}</p>
    <button @click="userStore.updateName('李四')">改名</button>
    <button @click="userStore.login('admin', '123456')">登录</button>
  </div>
</template>

<script setup>
// 导入定义好的 store
import { useUserStore } from './stores/user'

// 实例化 store
const userStore = useUserStore()
</script>

2. 解构 state(保持响应式)

直接解构会丢失响应式,必须用 storeToRefs

import { storeToRefs } from 'pinia'

// 正确写法:响应式解构
const { name, age, doubleAge } = storeToRefs(userStore)

// 注意:actions 不需要解构,直接用
const { updateName, login } = userStore

3. 批量修改 state

// 方式1:单个修改
userStore.name = '王五'

// 方式2:批量修改(推荐)
userStore.$patch({
  name: '赵六',
  age: 25
})

// 方式3:函数式批量修改(适合复杂逻辑)
userStore.$patch(state => {
  state.name = '孙七'
  state.age += 1
})

4. 重置 state 到初始值

userStore.$reset()

五、模块化与 Store 相互调用

Pinia 无需配置模块,直接导入其他 Store 即可使用

示例:cart 购物车 store 调用 user store

// src/stores/cart.js
import { defineStore } from 'pinia'
import { useUserStore } from './user'

export const useCartStore = defineStore('cart', {
  state: () => ({
    list: []
  }),
  actions: {
    addCart(goods) {
      const userStore = useUserStore()
      // 判断用户是否登录
      if (!userStore.token) {
        alert('请先登录')
        return
      }
      this.list.push(goods)
    }
  }
})

六、数据持久化(常用插件)

页面刷新后 Pinia 数据会丢失,使用 pinia-plugin-persistedstate 插件实现本地持久化。

1. 安装

pnpm add pinia-plugin-persistedstate

2. 全局注册

// main.js
import { createPinia } from 'pinia'
import piniaPluginPersistedstate from 'pinia-plugin-persistedstate'

const pinia = createPinia()
pinia.use(piniaPluginPersistedstate)

3. 开启持久化

// 在 store 中添加 persist: true
export const useUserStore = defineStore('user', {
  state: () => ({ ... }),
  persist: true // 开启持久化(默认 localStorage)
})

七、完整实战总结

  1. 安装 + 全局注册 Pinia
  2. 按功能拆分 Store(user/cart 等)
  3. state 存数据、getters 做计算、actions 做修改/异步
  4. 组件中导入使用,storeToRefs 解构保持响应式
  5. 跨模块调用直接导入其他 Store
  6. 用持久化插件保存数据不丢失

总结

  1. Pinia 是 Vue3 首选状态库,无 mutation、语法极简
  2. 核心三部分:state(数据)、getters(计算)、actions(方法)
  3. 响应式解构必须用 storeToRefs
  4. 模块化天然支持,持久化插件一键配置