Vue--》探索Pinia:Vue状态管理的未来

news/2025/2/27 23:03:39/

目录

Pinia的讲解与使用

Pinia的安装与使用

store数据操作

解构store数据

actions-getters的使用

Pinia常用API

持久化插件


Pinia的讲解与使用

Pinia 是由 Eduardo San Martin Morote 创建的,这是一个轻量级的、使用 Vue3 Composition API 的状态管理库。Pinia 于2020年8月正式发布,也就是在 Vue 3.0.0 版本推出后不久,可以说是比较新的一个状态管理解决方案。虽然 Pinia 是一种相对较新的解决方案,但它受到了许多 Vue.js 开发者的青睐,并在许多项目中得到广泛应用。

官方文档为:https://pinia.vuejs.org/zh/introduction.html ,从官网的图示我们不难看出,Pinia是专为 Vue.js 框架设计的状态管理解决方案,其核心是建立在 Vue 3 Composition API 之上的。因此Pinia 不能直接用于使用其他框架的项目。

但是,Pinia 可以与其他框架和库一起使用,例如在通过 Vue.js 构建的应用程序中,如果需要在 React 组件中使用 Pinia 中的状态,可以使用 Vue.js 手动渲染 React 组件的方法来实现。但是这种使用方式需要额外处理,使用起来可能会有一定的挑战性。如果你正在使用React,可以考虑使用专为React设计的状态管理方案,比如Redux,Mobx, Recoil等等。

那么我们在项目中该如何选择合适的状态管理工具进行使用?也就是说Pinia和Vuex的区别和应用场景到底有什么区别,别急,等我慢慢道来。

Pinia 和 Vuex 是 Vue.js 框架中两种常见的状态管理解决方案。它们都是用于管理响应式状态,但存在一些区别。如下:

API 的不同

Pinia 提供了一个更简单、更直接、易于理解的 API;而 Vuex 的 API 更加灵活,但也更为复杂,需要花费更多的时间学习。

全局状态的处理不同

在 Vuex 中有一个全局的 store(仓库),用于存储应用程序中的所有状态,而 Pinia 中则是一个基于类的 API,每个组件实例均有自己的 Pinia store,这使得应用程序的状态管理更加灵活、容易。此外,Pinia 还具有更好的 TypeScript 支持。

API 实时性的差异

在 Pinia 中,所有 getter 和 action 都会被实时更新,而在 Vuex 中只有 getter 会被实时更新,action 不会。

那么Pinia到底有啥特点能够吸引Vue开发者的对其竞相追逐呢?如下:

1)Pinia 是使用 TypeScript 编写的,它充分利用了 TypeScript 强类型系统的优点,提供了更好的类型声明和类型检查能力。

2)Pinia 的代码结构更加简洁明了,由于 Vue.js 3 在状态管理方面提供了更好的支持,Pinia 可以借助 Vue.js 3 的一些新特性来实现更简单、更直观的状态管理方案。

3)Pinia 支持插件,它提供了一个插件 API,可以将它与其他库和工具集成使用,如 devtools、vuex-persistedstate 等。

4)Pinia 通过提供 API 来支持响应式和异步操作,是一个更加灵活和可配置的状态管理方案。

5)在使用 Pinia 时,不需要像 Vuex 一样集中式地管理所有的状态,而是可以分成多个 Store,每个 Store 可以管理自己相关的状态。这种分离使代码结构更加清晰,易于维护。

总之,Pinia 相较于 Vuex 更加简单方便,不需要使用复杂的 API 和语法来管理应用状态,它还能够适应更广泛的应用场景,而 Vuex 则更加适用于复杂的状态管理需求。

Pinia的安装与使用

这里我采用的是vite构建工具进行创建的 vue3 最新项目,并结合TS的语言支持,如果你想在vue2中使用pinia,可自行查阅官网,这里不再赘述。如果不了解vite构建工具的朋友推荐看一下我之前讲解的文章:vite脚手架的搭建与使用 ,当然如果你是现成已经创建好的项目,直接执行如下命令安装库即可,这里不再赘述。

创建完项目后,终端执行如下命令进行安装Pinia库:

npm install pinia

安装完成之后,我们就可以在main.ts中进行引入Pinia相关配置代码,创建一个 pinia 实例 (根 store) 并将其传递给应用,如下:

import { createApp } from 'vue'
import App from './App.vue'
import { createPinia } from 'pinia'const store = createPinia()
let app = createApp(store)
app.use(store)createApp(App).mount('#app')

初始化仓库store: Store (如 Pinia) 是一个保存状态和业务逻辑的实体,它并不与你的组件树绑定。换句话说,它承载着全局状态。它有点像一个永远存在的组件,每个组件都可以读取和写入它。一般我们通常在 src 目录下新建文件夹 store ,里面存放中我们初始化仓库的文件代码:

在Pinia中 store是用defineStore()定义的,它的第一个参数是一个独一无二的名字,作为store中的唯一ID,Pinia 将用它来连接 store 和 devtools。为了方便处理ID,我将其单独抽离出来一个文件,用来枚举所有的pinia仓库ID,如下:

export const enum Names {Student = 'Student'
}

在store文件夹下新建index.ts文件,用来存放数据和操作的数据的方法:

import { defineStore } from "pinia";
import { Names } from "./storeName";// 将返回的函数命名为 use... 是一个符合组合式函数风格的约定。
export const useStudentStore = defineStore(Names.Student,{state:()=>({name:'张三',age:18})
})

在App.vue中我们进行引入store并将store中的数据进行渲染到界面上:

<template><div class="">Pinia:{{ Student.age }}</div>
</template><script setup lang="ts">
import { useStudentStore } from "./store"
const Student = useStudentStore()
</script>

在 vue 开发者工具中我们也可以看到我们创建的pinia数据。

store数据操作

直接修改

在pinia中我们可以直接对store中的数据进行操作,不再像vuex一样需要借助action才能进行:

<template><div class="">Pinia:{{ Student.age }}<button @click="change">修改</button></div>
</template><script setup lang="ts">
import { useStudentStore } from "./store"
const Student = useStudentStore()
const change = () =>{ Student.age++
}
</script>

$patch函数修改

如果想批量修改数据的话可以借助store身上的一个 $patch 函数,传入一个对象进行批量修改:

<template><div class="">Pinia:{{ Student.name }}Pinia:{{ Student.age }}<button @click="change">修改</button></div>
</template><script setup lang="ts">
import { useStudentStore } from "./store"
const Student = useStudentStore()
const change = () =>{ Student.$patch({name:'李四',age:20})
}
</script>

当然也可以采用函数式写法:

$state函数修改

当然也可以采用$state函数进行修改,但是缺陷是必须将state对象中的所有数据都进行修改,不能只单独修改某一个。

action函数修改

这里也可以借助store代码中的actions方法进行操作state中的数据,如下:

解构store数据

当我们使用store时,也可以采用解构方式,但是解构出来的store数据是非响应式的,如下:

<template><div class="">Pinia:{{ Student.name }}Pinia:{{ Student.age }}<p>解构后的数据</p>Pinia:{{ name }}Pinia:{{ age }}<button @click="change">修改</button></div>
</template><script setup lang="ts">
import { useStudentStore } from "./store"
const Student = useStudentStore()
const { name,age } = Student
const change = () =>{ Student.setChange('小张',10)
}
</script>

如果想将解构后的数据设置为响应式,可以采取这种方式

actions-getters的使用

在pinia中actions属性中可以调用同步函数和异步函数,如下:

同步函数的简单使用

import { defineStore } from "pinia";
import { Names } from "./storeName";type User = {name:string,age:number
}
let result:User = {name:'小王',age:100
}// 将返回的函数命名为 use... 是一个符合组合式函数风格的约定。
export const useStudentStore = defineStore(Names.Student,{state:()=>({person:<User>{}}),actions:{setChange(){this.person = result}}
})

在App.vue中直接调用函数即可:

异步函数的简单使用

import { defineStore } from "pinia";
import { Names } from "./storeName";type User = {name:string,age:number
}
const Login = ():Promise<User>=>{return new Promise((resolve)=>{setTimeout(()=>{resolve({name:'小明',age:100})},2000)})
}
// 将返回的函数命名为 use... 是一个符合组合式函数风格的约定。
export const useStudentStore = defineStore(Names.Student,{state:()=>({person:<User>{},name:'老王'}),actions:{async setChange(){const result = await Login( )this.person = resultthis.setName('小王')},setName(name:string){this.name = name}}
})

在pinia中getters属性中可以修饰一些值,如下:

Pinia常用API

pinia给我们也提供了一些常用的API,便捷我们日常的开发,如下:

$reset:重置state状态数据

$subscribe:响应state的变化

$onAction:响应actions的变化

持久化插件

pinia和vuex都有一个通病,就是页面一旦刷新数据就会丢失,我们希望刷新页面之后,数据将会在页面中进行保留,详情代码都放置在 mian.ts 中,如下:

import { createApp,toRaw } from 'vue'
import App from './App.vue'
import { createPinia, PiniaPluginContext } from 'pinia'const setStorage = (key:string,value:any) => {localStorage.setItem(key,JSON.stringify(value))
}
const getStorage = (key:string) =>{ return localStorage.getItem(key) ? JSON.parse(localStorage.getItem(key) as string) : {}
}type options = {key?:string
}
const __piniakey__:string = 'null'
const piniaPlugin = (options:options) => {return (context:PiniaPluginContext) => {const { store } = contextconst data = getStorage(`${options?.key ?? __piniakey__}-${store.$id}`)store.$subscribe(()=>{setStorage(`${options?.key ?? __piniakey__}-${store.$id}`,toRaw(store.$state))})console.log(store,'store')return {...data}}
}
const store = createPinia()
store.use(piniaPlugin({key:'pinpa'
}))
let app = createApp(store)
app.use(store)createApp(App).mount('#app')


http://www.ppmy.cn/news/69859.html

相关文章

Java设计模式-组合模式

简介 在软件设计中&#xff0c;设计模式是一种被广泛接受和应用的经验总结&#xff0c;旨在解决常见问题并提供可复用的解决方案。 组合模式是一种结构型设计模式&#xff0c;它允许将对象组合成树形结构以表示“部分-整体”的层次结构。这种模式能够使客户端以一致的方式处理…

软测人正在杀死软测行业

前言、一个软件做出来&#xff0c;最不能少的人是谁&#xff1f; 不用说就是开发&#xff0c;因为开发是最了解软件运作的那个人&#xff0c;早期不少一人撸网站或者APP的例子&#xff0c;相当于一个人同时是产品、研发、测试、运维等等&#xff0c;这也是为何开发是地位和上限…

【小沐学Python】Python实现在线英语翻译功能

文章目录 1、简介2、在线翻译接口2.1 Google Translate API2.2 Microsoft Translator API2.2.1 开发简介2.2.2 开发费用2.2.3 开发API 2.3 百度翻译开放平台 API2.3.1 开发简介2.3.2 开发费用2.3.3 开发API 2.4 Tencent AI 开放平台的翻译 API2.4.1 开发简介2.4.2 开发API 2.5 …

python3+telnetlib实现简单自动测试

1 telnetlib介绍 1.1 简介 官方介绍文档&#xff1a;telnetlib – Telnet 客户端 — Python 3.9.6 文档 telnetlib 模块提供一个实现Telnet协议的类 Telnet。 1.2 库常用函数及使用 1.2.1 建立连接 建立连接有两种方式&#xff1a;1、实例化函数的时候&#xff0c;将可选参数…

【SpringCloud微服务实践】提供与消费

提供与消费 文章目录 提供与消费创建服务提供者初始化项目项目配置定义User编写UserMapper编写Service层定义api接口返回格式编写Controller层 创建服务消费者配置User服务的地址创建RestTemplate Bean创建UserApi编写Controller层 总结 微服务属于分布式系统&#xff0c;微服务…

MySQL 字段为 NULL 的5大坑,大部分人踩过

数据库字段允许空值(null)的问题&#xff0c;小伙伴你遇到过吗&#xff1f; 在验证问题之前&#xff0c;我们先建一张测试表及测试数据。 构建的测试数据&#xff0c;如下图所示&#xff1a; 有了上面的表及数据之后&#xff0c;我们就来看当列中存在 NULL 值时&#xff0c;究…

调用百度文心AI作画API实现中文-图像跨模态生成

作者介绍 乔冠华&#xff0c;女&#xff0c;西安工程大学电子信息学院&#xff0c;2020级硕士研究生&#xff0c;张宏伟人工智能课题组。 研究方向&#xff1a;机器视觉与人工智能。 电子邮件&#xff1a;1078914066qq.com 一&#xff0e;文心AI作画API介绍 1. 文心AI作画 文…

web自动化测试进阶篇02 ——— BDD与TDD的研究实践

&#x1f60f;作者简介&#xff1a;博主是一位测试管理者&#xff0c;同时也是一名对外企业兼职讲师。 &#x1f4e1;主页地址&#xff1a;【Austin_zhai】 &#x1f646;目的与景愿&#xff1a;旨在于能帮助更多的测试行业人员提升软硬技能&#xff0c;分享行业相关最新信息。…