当前位置: 首页 > ds >正文

pinia状态管理工具

pinia状态管理工具

Pinia 是 Vue.js 官方推荐的新一代状态管理库,可以看作是 Vuex 的替代品。

1. 什么是 Pinia?

Pinia 是 Vue 的专属状态管理库,它允许你跨组件或页面共享状态。由 Vue.js 核心团队维护,并且对 TypeScript 有着极其出色的支持。

核心设计理念:

  • 直观: 像定义组件一样定义 Store,API 设计尽可能简单直观。
  • 类型安全: 全程提供出色的 TypeScript 支持,无需复杂的包装器。
  • 模块化: 可以拥有多个 Store,并自然地编码,让 Store 自动打包。
  • 轻量: 体积非常小(约 1KB),几乎不会增加打包负担。
  • Composition API: 完美契合 Vue 3 的 Composition API,但同时也支持 Option API。

2. 核心概念(与 Vuex 对比)

Pinia 的核心概念比 Vuex 更加简化,去掉了容易令人混淆的 mutations

概念VuexPinia说明
状态statestate存储应用状态数据的地方
获取状态gettersgetters用于计算和派生状态,相当于 Store 的计算属性
修改状态mutationsactions这是最大的不同。Pinia 中 actions 既可用于同步,也可用于异步操作
异步操作actionsactions在 Pinia 中,异步和同步操作都在 actions 中完成

简单来说,Pinia 就是:state + getters + actions


3. 安装与设置

1. 安装:

npm install pinia
# 或
yarn add pinia

2. 在 Vue 应用中创建并引入 Pinia:

main.jsmain.ts 中:

import { createApp } from 'vue'
import { createPinia } from 'pinia' // 导入 createPinia 函数
import App from './App.vue'// 创建 Pinia 实例
const pinia = createPinia()
// 创建 Vue 应用实例
const app = createApp(App)// 使用 Pinia
app.use(pinia)app.mount('#app')

4. 定义一个 Store

Pinia 使用 defineStore() 函数来定义一个 Store,它需要一个唯一名称(必填)作为第一个参数。这个名称是为了在 Devtools 中调试使用。

Store 有两种定义风格,类似于 Vue 的 Option APIComposition API

方式一:Option Store(选项式风格)

这种方式与 Vuex 的写法非常相似,更容易从 Vuex 迁移过来。

// stores/counter.js
import { defineStore } from 'pinia'export const useCounterStore = defineStore('counter', {// 状态数据state: () => ({count: 0,name: 'Eduardo',}),// 计算属性/派生状态getters: {doubleCount: (state) => state.count * 2,doubleCountPlusOne() { // 可以使用 this 访问整个 store 实例return this.doubleCount + 1},},// 操作方法(同步和异步)actions: {increment() {this.count++ // 通过 this 访问 state},async incrementAsync() {setTimeout(() => {this.increment() // 可以调用其他 action}, 1000)},},
})
方式二:Setup Store(组合式风格)

这种方式使用一个函数来定义 Store,类似于 Vue 的 setup() 函数和 Composition API。

// stores/counter.js
import { defineStore } from 'pinia'
import { ref, computed } from 'vue'export const useCounterStore = defineStore('counter', () => {// state (使用 ref)const count = ref(0)const name = ref('Eduardo')// getters (使用 computed)const doubleCount = computed(() => count.value * 2)const doubleCountPlusOne = computed(() => doubleCount.value + 1)// actions (使用普通函数)function increment() {count.value++}async function incrementAsync() {setTimeout(() => {increment()}, 1000)}// 返回所有需要暴露的状态和方法return {count,name,doubleCount,doubleCountPlusOne,increment,incrementAsync,}
})

如何选择?

  • 如果你习惯 Vuex 或 Option API,选 Option Store
  • 如果你喜欢 Composition API 的灵活性,选 Setup Store

5. 在组件中使用 Store

在组件中,你需要导入并调用你定义的 Store 函数(例如 useCounterStore)来使用它。Pinia 会自动管理单例。

访问 State 和 Getters
<template><div><p>Count: {{ counter.count }}</p><p>Double Count: {{ counter.doubleCount }}</p><p>Double Count Plus One: {{ counter.doubleCountPlusOne }}</p><p>Name: {{ name }}</p> <!-- 直接解构的 name --></div>
</template><script setup>
import { useCounterStore } from '@/stores/counter'
import { storeToRefs } from 'pinia' // 重要!用于保持响应式// 在 setup 中调用 Store 函数
const counter = useCounterStore()// ❌ 错误:直接解构会失去响应式!
// const { count, name } = counter// ✅ 正确:使用 storeToRefs 解构可以保持响应式
const { count, name } = storeToRefs(counter)
// 注意:actions 不需要也不应该用 storeToRefs 解构,直接通过 counter 调用即可
</script>
调用 Actions
<template><div><button @click="counter.increment()">Increment</button><button @click="counter.incrementAsync()">Increment Async</button></div>
</template><script setup>
import { useCounterStore } from '@/stores/counter'const counter = useCounterStore()// 也可以在方法或事件处理逻辑中调用
function handleClick() {counter.increment()
}
</script>

6. 状态修改与响应式

  • 直接修改: 你可以直接修改状态(counter.count++),这在 Pinia 中是允许的。
  • 批量修改: 使用 $patch 方法进行批量更新,这有利于性能优化,并且 Devtools 会将其记录为一次修改。
const counter = useCounterStore()// 方式一:传入一个部分 state 对象
counter.$patch({count: counter.count + 1,name: 'New Name',
})// 方式二:传入一个修改函数,适用于修改数组或嵌套对象
counter.$patch((state) => {state.items.push({ name: 'shoes', quantity: 1 })state.hasChanged = true
})
  • 替换整个状态: 可以通过 $state 属性替换整个 store 的状态。
counter.$state = { count: 1000, name: 'Paimon' }

7. 高级特性与技巧

订阅状态变化

可以使用 $subscribe 来监听 state 及其变化,类似于 Vuex 的 subscribe。常用于持久化等操作。

counter.$subscribe((mutation, state) => {// mutation 包含了修改的信息(events, type, storeId)// state 是修改后的新状态localStorage.setItem('counter', JSON.stringify(state))
})
订阅 Action

可以使用 $onAction 来监听 action 及其结果。

const unsubscribe = counter.$onAction(({ name, store, args, after, onError }) => {// action 调用前执行console.log(`Start "${name}" with params [${args.join(', ')}].`)// after 在 action 成功并返回后执行after((result) => {console.log(`Finished "${name}". Result was: ${result}.`)})// onError 在 action 抛出错误或 reject 时执行onError((error) => {console.warn(`Failed "${name}": ${error}.`)})
})// 手动移除订阅
// unsubscribe()
模块化(多 Store)

Pinia 天生是模块化的。你只需要定义多个不同的 Store 并在不同组件中引入它们即可。

// stores/user.js
export const useUserStore = defineStore('user', {state: () => ({ user: null }),// ...
})// stores/cart.js
export const useCartStore = defineStore('cart', {state: () => ({ items: [] }),// ...
})

然后在组件中可以同时使用多个 Store:

<script setup>
import { useUserStore } from '@/stores/user'
import { useCartStore } from '@/stores/cart'const userStore = useUserStore()
const cartStore = useCartStore()
// 甚至可以在一个 Store 中使用另一个 Store
// (注意避免循环引用)
</script>

总结:为什么选择 Pinia?

  1. 更简单的 API: 去除 mutations,只有 state, getters, actions,概念更清晰。
  2. 完美的 TS 支持: 无需复杂配置,类型推断非常强大。
  3. 模块化设计: 不需要嵌套模块,多个 Store 自然拆分。
  4. 轻量级: 体积极小,对应用打包体积影响几乎可以忽略不计。
  5. Composition API: 与 Vue 3 的编程思想完美契合,使用起来更加灵活。
  6. 官方推荐: 作为 Vuex 的继任者,是未来 Vue 生态的状态管理首选。

对于新项目,强烈推荐直接使用 Pinia。对于老项目,如果 Vuex 能满足需求且没有维护性问题,不一定需要立即迁移,但 Pinia 绝对是未来趋势。

http://www.xdnf.cn/news/19529.html

相关文章:

  • Redis核心原理与Java应用实践
  • 洞悉边界:软件测试中边界值分析的艺术与科学
  • OpenJDK 17 解释器分发表与安全点表机制解析
  • 零基础入门AutoSar中的ARXML文件
  • 【Flask】测试平台开发,产品管理功能UI重构-第九篇
  • Kubernetes 服务发现与健康检查详解
  • 搭建卷积神经网络
  • 软考 系统架构设计师系列知识点之杂项集萃(139)
  • C++11语言(三)
  • Nginx实现P2P视频通话
  • codecombat(Ubuntu环境详细docker部署教程)
  • 项目-云备份
  • 面试 八股文 经典题目 - HTTPS部分(一)
  • Flink NettyBufferPool
  • 大模型时代:用Redis构建百亿级向量数据库方
  • EtherCAT主站IGH-- 41 -- IGH之sdo_request.h/c文件解析
  • Library cache lock常见案例分析(一)
  • Encoder编码器
  • 图像描述编辑器 (Image Caption Editor)
  • 极客时间AI 全栈开发实战营毕业总结(2025年8月31日)
  • 【Linux基础】深入理解计算机存储:GPT分区表详解
  • 前端组件拆分与管理实战:如何避免 props 地狱,写出高可维护的项目
  • 《Unity Shader入门精要》学习笔记四(高级纹理)
  • ing Data JPA 派生方法 数据操作速查表
  • 【WEB】[BUUCTF] <GXYCTF2019禁止套娃>《php函数的运用》
  • ADC platfrom day65
  • MVC架构模式
  • Blender建模:对于模型布线的一些思考
  • 介绍GSPO:一种革命性的语言模型强化学习算法
  • 现代C++性能陷阱:std::function的成本、异常处理的真实开销