Vue Pinia 插件详解

Pinia 是 Vue.js 官方推荐的状态管理库(自 Vue 3 起),用于替代 Vuex。它具有更简洁的 API、更好的 TypeScript 支持、模块化设计以及对 Composition API 的天然适配。

一、Pinia 简介

  • 作者:Eduardo San Martin Morote(Vue 团队核心成员)
  • 特点 :
    • 无 mutations,只有 state、getters、actions
    • 支持 Vue 2(≥2.6.14)和 Vue 3
    • 完美支持 TypeScript(无需额外配置)
    • 支持 Vue Devtools 调试
    • 支持服务端渲染(SSR)
    • 模块自动注册,无需手动嵌套
    • 轻量(gzip 后约 1KB)

二、安装与基本使用

  1. 安装
bash 复制代码
# Vue 3 项目
npm install pinia

# Vue 2 项目(需额外安装 composition-api)
npm install pinia @vue/composition-api
  1. 在 Vue 应用中注册
javascript 复制代码
// main.js (Vue 3)
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')
注意:Vue 2 中使用 new Vue({ pinia }) 语法。 

三、定义 Store

使用 defineStore 创建 store,接受两个参数:id 和 配置对象(或函数)。

  1. 选项式写法(类似 Vuex)
javascript 复制代码
// stores/counter.js
import { defineStore } from 'pinia'

export const useCounterStore = defineStore('counter', {
  state: () => ({
    count: 0,
    name: 'Eduardo'
  }),

  getters: {
    doubleCount: (state) => state.count * 2,
    // 带参数的 getter(使用箭头函数返回函数)
    doubleCountPlus: (state) => (n) => state.count * 2 + n
  },

  actions: {
    increment() {
      this.count++
    },
    reset() {
      this.count = 0
    },
    // 支持异步
    async fetchData() {
      const res = await fetch('/api/data')
      this.data = await res.json()
    }
  }
})
  1. 函数式写法(使用 Composition API)
javascript 复制代码
import { defineStore } from 'pinia'
import { ref, computed } from 'vue'

export const useCounterStore = defineStore('counter', () => {
  const count = ref(0)
  const name = ref('Eduardo')

  const doubleCount = computed(() => count.value * 2)

  function increment() {
    count.value++
  }

  function reset() {
    count.value = 0
  }

  return { count, name, doubleCount, increment, reset }
})

✅ 推荐函数式写法:更灵活、复用性强、便于单元测试。

四、在组件中使用 Store

javascript 复制代码
<template>
  <div>
    <p>Count: {{ counter.count }}</p>
    <p>Double: {{ counter.doubleCount }}</p>
    <button @click="counter.increment">+</button>
    <button @click="reset">Reset</button>
  </div>
</template>

<script setup>
import { useCounterStore } from '@/stores/counter'

const counter = useCounterStore()

// 解构会丢失响应性!应使用 toRefs 或 storeToRefs
// ❌ 错误写法:
// const { count, increment } = counter

// ✅ 正确写法(推荐):
import { storeToRefs } from 'pinia'
const { count, doubleCount } = storeToRefs(counter)
const { increment } = counter
</script>

五、核心特性详解

  1. 自动响应性

State 是响应式的,修改会自动触发视图更新。

Getters 是缓存的 computed 属性。

  1. Actions

替代 mutations + actions。

可同步/异步。

可调用其他 store 的 actions。

javascript 复制代码
// 调用其他 store
const useUserStore = defineStore('user', {
  actions: {
    async login() {
      const counter = useCounterStore()
      counter.increment()
    }
  }
})
  1. Store 间通信

直接 import 并调用其他 store。

无命名空间冲突(每个 store 有唯一 ID)。

  1. TypeScript 支持

开箱即用,无需额外配置。

类型推导精准。

javascript 复制代码
interface User {
  id: number
  name: string
}

export const useUserStore = defineStore('user', () => {
  const users = ref<User[]>([])
  // 类型自动推导 ✅
})

六、插件系统(Plugin)

Pinia 支持插件扩展功能(类似 Vuex 的插件)。

示例:添加 localStorage 持久化

javascript 复制代码
// plugins/persist.js
export const persistPlugin = ({ store }) => {
  const key = `pinia:${store.$id}`
  
  // 初始化时从 localStorage 读取
  const saved = localStorage.getItem(key)
  if (saved) {
    store.$state = JSON.parse(saved)
  }

  // 监听状态变化并保存
  store.$subscribe((mutation, state) => {
    localStorage.setItem(key, JSON.stringify(state))
  })
}

// main.js
import { createPinia } from 'pinia'
import { persistPlugin } from './plugins/persist'

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

插件可扩展内容:

添加属性到 store(如 $db)

修改 $state

添加新选项(如 $reset)

七、服务端渲染(SSR)支持

Pinia 原生支持 SSR,只需在服务端创建新的 Pinia 实例:

javascript 复制代码
// server-entry.js
import { createPinia } from 'pinia'

export function createApp() {
  const app = createApp(App)
  const pinia = createPinia()
  app.use(pinia)
  return { app, pinia }
}

自动处理 hydration,无需额外配置。

八、Devtools 调试

  • 自动集成 Vue Devtools。
  • 可追踪 actions 调用、状态变化。
  • 时间旅行调试(time-travel debugging)。

九、与 Vuex 对比

API 简洁性 ✅ 更简洁(无 mutations) ❌ 较复杂
TypeScript ✅ 原生支持 ⚠️ 需额外配置
模块嵌套 ✅ 扁平化(自动注册) ❌ 需手动嵌套
Composition API ✅ 天然支持 ❌ 需额外适配
包体积 ✅ 更小 ❌ 较大
Vue 2 支持 ✅(需插件) ✅

十、最佳实践

  1. 每个 store 单文件 :stores/user.js、stores/product.js
  2. 使用函数式定义:便于逻辑复用和测试
  3. 避免直接修改 state:始终通过 actions
  4. 使用 storeToRefs 解构:保持响应性
  5. 合理拆分 store:按业务域划分,不要一个 store 管所有状态
相关推荐
এ慕ོ冬℘゜7 小时前
es6基础
前端·javascript·es6
熊猫钓鱼>_>7 小时前
从2D平铺到3D沉浸:我用HarmonyOS 7端侧AI做了一个全程数据不出设备的空间化私密相册
前端·人工智能·3d·华为·华为云·harmonyos·鸿蒙
ym hyd 1117 小时前
汽车零部件缺陷管理系统源码 Java+SpringBoot+Vue3 前后分离
java·vue.js·spring boot·汽车·毕设
孔令飞8 小时前
Go中指针引用Go中指针引用Go中指针引用Go中指针引用Go中指针引用Go中指针引用Go中指针引用Go中指针引用Go中指针引用Go中指针引用Go中指针引用Go中
前端
可乐鸡翅yeah_8 小时前
hls.js 缓冲区参数 maxBufferLength、maxBufferSize 通俗讲解与业务调参
开发语言·javascript·ios·音视频·safari·m3u8
溪语流沙8 小时前
【Web全栈进阶】PostgreSQL上手:Docker跑库 + 把早报站从SQLite迁过去
前端·docker·postgresql
IT_陈寒8 小时前
SpringBoot自动配置的坑:你以为的捷径可能是弯路
前端·人工智能·后端
paopaokaka_luck8 小时前
高校社团管理(AI辅助任务分配、协同过滤算法推荐、ECharts数据可视化、活动参与闭环、校园交流与反馈、器材借还管理)
java·前端·javascript·spring boot·数据分析·echarts
vx_Biye_Design8 小时前
springboot小区管理系统68491-计算机课程设计、毕业设计
java·vue.js·spring boot·后端·spring·课程设计·express
500848 小时前
React Native for OpenHarmony 实战:三方库 react-native-volume-control 的鸿蒙化适配指南
javascript·react native·react.js·electron·harmonyos