Vue状态管理库Pinia详解

种地  金牌会员 | 2024-8-23 09:25:51 | 显示全部楼层 | 阅读模式
打印 上一主题 下一主题

主题 931|帖子 931|积分 2793

Pinia 是 Vue 的状态管理库,它提供了一种更简单、更不规范的 API 来管理应用的状态。Pinia 的筹划哲学是简单性和易用性,它制止了 Vuex 中的许多复杂概念,如 mutations 和模块的嵌套结构,提供了一种更当代、更符合 Vue 3 Composition API 风格的状态管理方式。
先来瞅一眼 Pinia 的核心组件主要包括以下几个方面:

  • Store:Pinia 中的 Store 是一个保存状态和业务逻辑的实体,它不与组件树绑定,可以在整个应用中访问。Store 包含三个核心概念:state(状态)、getters(获取器)、actions(动作)。这些概念类似于组件中的 data、computed 和 methods。
  • defineStore() :这是定义 Store 的函数,需要传入一个独一无二的名字作为 ID,用于连接 Store 和 devtools。Store 可以通过 Setup 函数或 Option 对象来定义。
  • reactive:虽然 Pinia 本身不要求利用 Composition API,但它与 Vue 的 reactive 系统精麋集成,允许开发者以声明式的方式管理状态。
  • Devtools 支持:Pinia 支持 Vue Devtools,提供了追踪 actions 和 mutations 的时间线、时间观光和热更新等功能,方便开发者调试。
  • 插件系统:Pinia 允许通过插件来扩展其功能,比方支持服务器端渲染或添加额外的中间件。
  • TypeScript 支持:Pinia 提供了对 TypeScript 的良好支持,包括类型推断和自动补全功能,使得在 TypeScript 项目中利用 Pinia 更加方便 。
  • SSR 支持:Pinia 支持服务端渲染,这对于构建需要 SSR 的应用是一个重要的特性。
  • 映射辅助函数:Pinia 提供了如 mapStores、mapState 和 mapActions 等辅助函数,使得在组件中利用 Store 更加方便。
下面是每个部分的详细先容。
1. Store

在 Pinia 中,Store 是用来封装应用的状态和逻辑的核心概念。它允许你将状态和行为集中管理,而不是分散在各个组件中。Store 可以包含以下几部分:

  • state:状态数据,通常是响应式的,可以在组件中被读取和修改。
  • getters:计算属性,用于派生状态,它们是响应式的,并且可以被缓存。
  • actions:可以包含任意的异步操纵或同步操纵,用于修改状态或实行复杂的业务逻辑。
案例实现

下面是一个创建 Store 的步调剖析,包括代码示例:
步调 1: 定义 Store

首先,你需要从 Pinia 导入 defineStore 函数,并利用它来定义一个新的 Store。
  1. import { defineStore } from 'pinia'
  2. export const useUserStore = defineStore('user', {
  3.   state: () => ({
  4.     users: [] // 初始状态是一个空数组
  5.   }),
  6.   getters: {
  7.     // 一个 getter 函数,返回数组中的用户数量
  8.     count: (state) => state.users.length
  9.   },
  10.   actions: {
  11.     // 一个 action 函数,用于添加用户
  12.     addUser(user) {
  13.       this.users.push(user)
  14.     }
  15.   }
  16. })
复制代码
步调 2: 在组件中利用 Store

在 Vue 组件中,你可以通过调用你定义的 useUserStore 函数来利用这个 Store。
  1. <template>
  2.   
  3.     <button @click="addNewUser">添加用户</button>
  4.     <p>用户总数: {{ userCount }}</p>
  5.     <ul>
  6.       <li v-for="user in users" :key="user.id">{{ user.name }}</li>
  7.     </ul>
  8.   
  9. </template>
复制代码
代码剖析

<ul>导入 defineStore:从 Pinia 导入 defineStore 函数来定义新的 Store。
定义 useUserStore:创建一个名为 useUserStore 的函数,它返回一个 Store 对象。
state:在 Store 中定义了一个状态 users,初始为空数组。
getters:定义了一个 count getter,它返回 users 数组的长度。
actions:定义了一个 addUser action,它接受一个用户对象并将其添加到 users 数组中。
在组件中利用:在组件的 [/code]代码剖析

<ul>导入 defineStore:从 Pinia 导入 defineStore 函数。
定义 useCartStore:创建一个名为 useCartStore 的函数,它返回一个设置好的 Store 对象。
state:在 Store 中定义了一个状态 items,初始为空数组,用于存储购物车中的商品。
getters:定义了一个 itemCount getter,它通过遍历 items 数组并累加每个商品的 quantity 来计算总数量。
actions:定义了 addItem 和 clearCart 两个 actions。addItem 用于向购物车添加商品,如果商品已存在则增长其数量;clearCart 用于清空购物车。
在组件中利用:在组件的 [/code]代码剖析

<ul>导入 reactive:从 Vue 导入 reactive 函数。
创建响应式状态:利用 reactive() 创建一个包含 count 和 message 的响应式状态对象。
在 Pinia Store 中利用 reactive:在 defineStore() 的 state 函数中返回一个 reactive() 对象,这样 Pinia 就可以管理这个状态的响应性。
在组件中利用:在组件的 [/code]步调 5: 利用 Vue Devtools 调试


  • 打开浏览器的开发者工具。
  • 切换到 Vue Devtools 面板。
  • 在“Components”或“Store”标签页中,你应该能看到你的 Pinia Store。
  • 展开 Store,查看 state、getters 和 actions。
  • 点击 actions,你可以看到它们的调用汗青和参数。
  • 直接在 Devtools 中修改 state 的值,看应用如何响应这些变革。
代码过程步调剖析


  • 安装 Devtools:确保浏览器扩展已安装。
  • 创建 Store:利用 defineStore 创建一个包含 state、getters 和 actions 的 Pinia Store。
  • 应用设置:在应用启动时创建 Pinia 实例并利用它。
  • 组件利用:在组件中通过调用 Store 函数来获取 Store 实例,并利用 computed 属性来保持响应性。
  • 调试:利用 Vue Devtools 查看和修改状态,追踪 actions。
利用 Vue Devtools 提供的功能来调试利用 Pinia 管理状态的 Vue 应用,感觉是不是挺爽。
5. 插件系统

Pinia 的插件系统允许开发者扩展 Pinia 的功能。插件可以访问 Pinia 的 Store 创建过程,可以实行以下操纵:

  • 在 Store 创建之前或之后实行自定义逻辑。
  • 拦截 Store 的 state、getters、actions 等属性。
  • 向 Store 添加自定义属性或方法。
  • 处置惩罚 Store 的销毁逻辑。
Pinia 插件通常在创建 Pinia 实例时注册,然后 Pinia 会将插件应用到每个创建的 Store 上。
案例实现

下面是一个创建和利用 Pinia 插件的步调剖析,包括代码示例:
步调 1: 定义插件

首先,定义一个插件函数,该函数接收 Pinia 的实例作为参数。
  1. function myPiniaPlugin(pinia) {
  2.   // 插件逻辑
  3. }
复制代码
步调 2: 插件逻辑

在插件函数内部,可以访问 Pinia 的 store 对象,并对其进行操纵。
  1. function myPiniaPlugin(pinia) {
  2.   pinia.use((store) => {
  3.     // 可以在此处访问 store.state, store.getters, store.actions 等
  4.     // 例如,向 store 添加一个新属性
  5.     store.myCustomProperty = 'Hello from plugin!'
  6.   })
  7. }
复制代码
步调 3: 创建 Pinia 实例并利用插件

创建 Pinia 实例时,利用 use 方法注册插件。
  1. import { createPinia } from 'pinia'
  2. const pinia = createPinia().use(myPiniaPlugin)
复制代码
步调 4: 创建 Store

定义一个 Store,利用 defineStore 函数。
  1. import { defineStore } from 'pinia'
  2. export const useMyStore = defineStore('myStore', {
  3.   // state, getters, actions 定义
  4.   state: () => ({
  5.     value: 0
  6.   }),
  7.   // 其他选项...
  8. })
复制代码
步调 5: 在组件中利用 Store

在组件中利用 Store,并访问插件添加的属性。
  1. <template>
  2.   
  3.     <p>Value: {{ value }}</p>
  4.     <p>Plugin Property: {{ store.myCustomProperty }}</p>
  5.   
  6. </template>
复制代码
步调 6: 组件中利用插件属性

在组件的模板或脚本中,利用插件添加到 Store 的自定义属性。
  1. // 在模板中
  2. <p>Plugin Property: {{ store.myCustomProperty }}</p>
  3. // 在脚本中
  4. console.log(store.myCustomProperty) // 输出: Hello from plugin!
复制代码
代码过程步调剖析


  • 定义插件:创建一个函数,该函数接收 Pinia 实例并定义插件逻辑。
  • 插件逻辑:在插件函数内部,利用 pinia.use 方法注册一个回调,该回调接收每个 Store 并可以对其进行操纵。
  • 注册插件:在创建 Pinia 实例时,通过 .use() 方法注册插件。
  • 创建 Store:利用 defineStore 定义 Store,包括 state、getters、actions。
  • 利用 Store:在组件中利用 Store,并利用 computed 属性保持响应性。
  • 访问插件属性:在组件的模板或脚本中,访问插件添加到 Store 的自定义属性。
记住这一点,开发者需要添加自定义逻辑和属性,通过Pinia 插件系统就 OK。
6. TypeScript 支持

Pinia 为 TypeScript 用户提供了一流的支持,确保类型安全和开发体验。Pinia 的 TypeScript 支持主要体现在以下几个方面:

  • 类型推断:Pinia 利用 TypeScript 的高级类型系统来推断 Store 中的状态、getters 和 actions 的类型。
  • 类型声明:Pinia 提供了类型声明文件(.d.ts),确保 Pinia API 在 TypeScript 项目中的类型正确性。
  • 自动补全:在 TypeScript 环境中,编辑器可以提供自动补全功能,帮助开发者快速编写代码。
  • 类型守卫:Pinia 与 TypeScript 共同利用时,可以利用类型守卫来确保对 Store 属性的访问是安全的。
案例实现

下面是一个利用 TypeScript 与 Pinia 团结利用的步调剖析,包括代码示例:
步调 1: 设置 TypeScript 环境

确保你的项目已经设置了 TypeScript,并且安装了必要的类型声明文件。
  1. npm install typescript @vue/compiler-sfc
复制代码
步调 2: 定义 Store 利用 TypeScript

利用 TypeScript 的类型定义来创建 Pinia Store。
  1. import { defineStore } from 'pinia'
  2. interface State {
  3.   count: number
  4.   message: string
  5. }
  6. export const useMyStore = defineStore('myStore', {
  7.   state: (): State => ({
  8.     count: 0,
  9.     message: 'Hello, Pinia with TypeScript!'
  10.   }),
  11.   getters: {
  12.     // 使用 TypeScript 来声明 getter 的返回类型
  13.     doubleCount: (state): number => state.count * 2
  14.   },
  15.   actions: {
  16.     increment(): void {
  17.       this.count++
  18.     }
  19.   }
  20. })
复制代码
步调 3: 在组件中利用 Store

在 Vue 组件中利用 Store,并利用 TypeScript 提供类型安全。
  1. <template>
  2.   
  3.     <p>Count: {{ count }}</p>
  4.     <p>Message: {{ message }}</p>
  5.     <p>Double Count: {{ doubleCount }}</p>
  6.     <button @click="increment">Increment</button>
  7.   
  8. </template>
复制代码
步调 4: 利用类型守卫

利用类型守卫来确保对 Store 属性的访问是安全的。
  1. if (store.hasOwnProperty('count')) {
  2.   // TypeScript 知道 'count' 存在且为 number 类型
  3.   console.log(store.count)
  4. }
复制代码
代码过程步调剖析


  • 设置 TypeScript:确保项目中安装了 TypeScript 及其类型声明文件。
  • 定义 Store 类型:利用 TypeScript 的接口(interface)来定义 Store 的状态类型。
  • 创建 Store:利用 defineStore 并传入类型化的 state 函数,以及声明了返回类型的 getters 和 actions。
  • 组件中利用 Store:在组件中利用 TypeScript 来确保访问 Store 属性的类型安全。
  • 类型守卫:利用 TypeScript 的 hasOwnProperty 方法和类型守卫来安全地访问 Store 的属性。
小结一下,Pinia 与 TypeScript 团结利用可以提供类型安全的状态管理,同时编辑器的自动补全和类型检查功能可以提高开发服从和淘汰错误。
7. SSR 支持

服务器端渲染(SSR)是一种将网站页面在服务器上生成并发送给客户端的技术。对于状态管理库来说,SSR 支持意味着可以在服务器上初始化和操纵状态,然后将状态序列化后发送到客户端,客户端再将这些状态恢复以保持与服务器端相同的状态。
Pinia 对 SSR 的支持主要体现在以下几个方面:

  • 状态序列化:Pinia 允许将状态(state)序列化成 JSON 字符串,以便在服务器和客户端之间传输。
  • 状态恢复:客户端可以接收服务器端的状态,并将其恢复到对应的 Store 中。
  • 无状态的 Store 定义:Pinia 的 Store 定义是无状态的,这意味着在服务器端和客户端端都可以重新创建 Store。
  • 与 Vue SSR 的集成:Pinia 可以与 Vue 的 SSR 系统集成,确保在服务器端预渲染组件时利用正确的状态。
案例实现

下面是一个利用 Pinia 进行 SSR 的步调剖析,包括代码示例:
步调 1: 定义 Store

首先,定义一个 Pinia Store。
  1. import { defineStore } from 'pinia'
  2. export const useMyStore = defineStore('myStore', {
  3.   state: () => ({
  4.     count: 0
  5.   }),
  6.   // 其他选项...
  7. })
复制代码
步调 2: 在服务器端创建和序列化状态

在服务器端,创建 Store 实例并初始化状态,然后将状态序列化。
  1. // server.js
  2. import { createPinia } from 'pinia'
  3. import useMyStore from '@/stores/myStore'
  4. const pinia = createPinia()
  5. // 模拟从数据库获取初始状态
  6. const initialState = { count: 10 }
  7. // 创建 Store 实例并设置初始状态
  8. const store = useMyStore(pinia)
  9. store.$state.count = initialState.count
  10. // 序列化状态
  11. const stateToTransfer = JSON.stringify(store.$state)
复制代码
步调 3: 在客户端恢复状态

在客户端,接收服务器端发送的状态,然后恢复到对应的 Store 中。
  1. // client.js
  2. import { createPinia } from 'pinia'
  3. import { createApp } from 'vue'
  4. import App from './App.vue' // Vue 应用的根组件
  5. import useMyStore from '@/stores/myStore'
  6. const pinia = createPinia()
  7. // 假设从服务器接收的状态如下
  8. const stateFromServer = JSON.parse(/* state serialized from server */)
  9. // 创建 Store 实例并恢复状态
  10. const store = useMyStore(pinia)
  11. store.$state.count = stateFromServer.count
  12. const app = createApp(App)
  13. app.use(pinia)
  14. app.mount('#app')
复制代码
步调 4: 在 Vue 组件中利用 Store

在 Vue 组件中,像平常一样利用 Store。
  1. <template>
  2.   {{ count }}
  3. </template>
复制代码
代码过程步调剖析


  • 定义 Store:利用 defineStore 定义一个 Pinia Store。
  • 服务器端创建和序列化:在服务器端,创建 Store 实例,设置初始状态,并利用 JSON.stringify 序列化状态。
  • 客户端恢复状态:在客户端,剖析服务器端发送的状态字符串,并恢复到 Store 的 $state 中。
  • 组件中利用 Store:在 Vue 组件中,通过调用 Store 函数获取 Store 实例,并利用 computed 属性来访问状态。
一句话,Pinia支持SSR有助于提高应用的初始加载性能和SEO优化。
8. 映射辅助函数

在 Pinia 中,映射辅助函数用于将 Store 中的状态(state)、获取器(getters)、动作(actions)映射到组件的计算属性(computed properties)、方法(methods)或响应式属性上。这些辅助函数提供了一种便捷的方式来利用 Store,而无需在每个组件中重复编写相同的代码。
Pinia 的映射辅助函数主要包括:

  • mapState:将 Store 中的状态映射为组件的计算属性。
  • mapGetters:将 Store 中的获取器映射为组件的计算属性。
  • mapActions:将 Store 中的动作映射为组件的方法。
案例实现

下面是一个利用 Pinia 映射辅助函数的步调剖析,包括代码示例:
步调 1: 定义 Store

首先,定义一个 Pinia Store。
  1. import { defineStore } from 'pinia'
  2. export const useCartStore = defineStore('cart', {
  3.   state: () => ({
  4.     items: []
  5.   }),
  6.   getters: {
  7.     itemCount: (state) => state.items.length
  8.   },
  9.   actions: {
  10.     addItem(item) {
  11.       this.items.push(item)
  12.     }
  13.   }
  14. })
复制代码
步调 2: 利用映射辅助函数

在组件中,利用 mapState、mapGetters 和 mapActions 将 Store 的属性映射到组件上。
  1. <template>
  2.   
  3.     <p>Item Count: {{ itemCount }}</p>
  4.     <button @click="addItem({ id: 1, name: 'Apple' })">Add Apple</button>
  5.   
  6. </template>
复制代码
步调 3: 在模板中利用映射的属性

在组件的模板中,直接利用映射的计算属性和方法。
  1. <p>Item Count: {{ itemCount }}</p>
  2. <button @click="addItem({ id: 1, name: 'Apple' })">Add Apple</button>
复制代码
代码过程步调剖析


  • 定义 Store:利用 defineStore 定义一个包含状态、获取器和动作的 Pinia Store。
  • 利用映射辅助函数

    • mapState:将 items 状态映射为组件的计算属性。
    • mapGetters:将 itemCount 获取器映射为组件的计算属性。
    • mapActions:将 addItem 动作映射为组件的方法。

  • 模板中利用:在模板中,利用映射的计算属性 itemCount 来显示项目数量,利用映射的方法 addItem 来添加新项目。
利用映射辅助函数,Pinia 可以让开发者以声明式的方式在组件中利用 Store 的状态和行为,从而淘汰样板代码并提高组件的可读性和可维护性。别的,这些辅助函数还有助于保持响应性,确保当 Store 中的状态变革时,组件能够自动更新。
最后

不得不说,Pinia 提供了一种机动且高效的方式来管理 Vue 应用的状态,无论是在单页应用还是服务器端渲染的场景下,都有出色的表现,写完收工,接待关注威哥爱编程,一起走全栈之路。

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

正序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

种地

金牌会员
这个人很懒什么都没写!
快速回复 返回顶部 返回列表