Pinia的由来
Pinia(发音为 /piːnjʌ/,类似于英语中的“peenya”)是最接近有效包名 piña(西班牙语中的pineapple,即“菠萝”)的词。 菠萝实际上是一组单独的花朵,它们结合在一起形成一个多重水果。 与 Store 类似,每一家都是独立诞生的,但最终都是相互联系的。用来比喻把一个一个的小格子数据,集中式管理在一起,所以也有很多开发者,习惯性的把 Pinia 称呼为“小菠萝”!它也是一种美味的热带水果,原产于南美洲。
Pinia 是由 Vue.js 团队成员开发,最初是为了探索 Vuex 下一次迭代会是什么样子。过程中,Pinia 实现了 Vuex5 提案的大部分内容,于是就取而代之了。与 Vuex 相比,Pinia 提供了更简单的 API,更少的规范,以及 Composition-API 风格的 API 。更重要的是,与 TypeScript 一起使用具有可靠的类型推断支持。
如果你学过Vue2,那么你一定使用过Vuex。我们都知道Vuex在Vue2中主要充当状态管理的角色,所谓状态管理,简单来说就是一个存储数据的地方,存放在Vuex中的数据在各个组件中都能访问到,它是Vue生态中重要的组成部分。
在Vue3中,可以使用传统的Vuex来实现状态管理,也可以使用最新的Pinia来实现状态管理,我们来看看官网如何解释Pinia的:Pinia 是 Vue 的存储库,它允许跨组件/页面共享状态。从官网的解释不难看出,Pinia和Vuex的作用其实是一样的,它也充当的是一个存储数据的作用,存储在Pinia的数据允许我们在各个组件中使用。实际上,Pinia就是Vuex的升级版,官网也说过,为了尊重原作者,所以取名Pinia,而没有取名Vuex,所以大家可以直接将Pinia比作为Vue3的Vuex。
为什么使用Pinia
很多小伙伴可能会抛出一系列的疑问:为什么要学习Pinia?Pinia有什么优点吗?既然Vue3还能使用Vuex为什么我还要学它?
这些问题其实都有答案,我们不可能平白无故的而去学习一样东西吧!肯定它有自己的优点的,所以这里我们先列出Pinia的优点:
- Vue2和Vue3都支持。
- Pinia中只有state、getters、actions,抛弃了Vuex中的Mutation,Vuex中mutation一直都不太受小伙伴们的待见,Pinia直接抛弃它了,这无疑减少了我们工作量。
- Pinia中actions支持同步和异步,Vuex不支持。
- 良好的Typescript支持,我们知道Vue3都推荐使用TS来编写,这个时候使用Pinia就非常合适了。
- 无需再创建各个模块嵌套了,Vuex中如果数据过多,我们通常分模块来进行管理,稍显麻烦,而Pinia中每个store都是独立的,互相不影响。
- 体积非常小,只有1KB左右。
- Pinia支持插件来扩展自身功能。
- 支持服务端渲染。
这张是vuex跟pinia的区别,应该显而易见,pinia的每个store都是独立的
Pina的基础特性:
State
- 默认情况下,通过 store 实例访问 state,可以直接读取和写入,如 @click=“store.count++”。
- 通过 store.$reset() 方法可以将 state 重置为初始值。
- 除了直接通过 store 修改 state,还可以通过 store.$patch() 方法提交多个更改。
Getters
- Getters 属性的值是一个函数,接受 state 作为第一个参数,目的是鼓励使用箭头函数。
- 非箭头函数会绑定 this,建议仅在需要获取整个 store 实例的场景使用,且需要显式定义函数返回类型。
Actions
- 与 Gettes 一样可以通过 this 访问整个 store 实例。
- Actions 可以是异步的或同步的,不管怎样,都会返回一个 Promise。
- Actions 可以自由的设置参数和返回的内容,一切将自动推断,不需要定义TS 类型。
Pinia的基本使用
1. 创建一个项目,安装pinia
2. 创建store以及使用store
3. 添加state以及操作state
4. getters属性
5. actions属性
因为Pinia基本都是基于Vue3使用,至于Vue2中如何使用,这里就不讲解了,可以自行去Pinia官网学习,毕竟Vue2中使用pinia的还是少数。官网地址:https://pinia.web3doc.top/
1.1.创建一个最新的Vue3 + TS + Vite项目
执行命令:npm create vite@latest pinia-vite-demo --template vue-ts
1.2.运行项目:
执行命令:npm install
然后npm run dev
1.3.安装pinia:
执行命令:yarn add pinia 或者使用npm npm install pinia
1.4.安装完成后我们需要将 pinia 挂到 vue 应用中,也就是我们需要创建一个根存储传递给应用程序,简单来说就是创建一个存储数据的数据桶,放到应用程序中去。需要修改main.ts/js文件,引入pinia提供的createPinia方法,创建根存储。
import { createApp } from 'vue'
import './style.css'
import App from './App.vue'
//引入pinia提供的createPinia方法,创建根存储
import {createPinia} from 'pinia'
const pinia = createPinia();
const app = createApp(App);
app.use(pinia)
app.mount('#app')
2.1.创建store,那什么是store呢?
(官网解释)一个 Store (如 Pinia)是一个实体,它持有未绑定到您的组件树的状态和业务逻辑。换句话说,它托管全局状态。它有点像一个始终存在并且每个人都可以读取和写入的组件。它有三个概念,state、getters 和 actions 并且可以安全地假设这些概念等同于组件中的“数据”、“计算”和“方法”。
我们可以把这三个概念理解为vue组件中的“数据”data、“计算”computed和“方法”methods。store简单来说就是数据仓库的意思,我们数据都放在store里面。我们也可以把它理解为一个公共的组件,只不过该公共组件只存放数据,这些数据我们其它所有的组件都能够访问且可以修改。
我们需要使用pinia提供的defineStore()方法来创建一个store,该store用来存放我们需要全局使用的数据。首先在项目src目录下新建store文件夹,用来存放我们创建的各种store,然后在该目录下新建xxx.ts文件,主要用来存放与xxx相关的store,不同的store用来存放不同的全局数据,相当于把它们进行了分类,方便我们更好的管理。一旦 store 被实例化,你就可以直接在 store 上访问 state、getters 和 actions 中定义的任何属性。
比如有一个用户相关的数据,我们可以在store目录下创建一个user.ts,还有一个产品相关的数据,再创建一个product.ts,这两个没有关联的数据,我们可以分别给他们创建一个store来管理,代码如下:
//创娃store很简单,调用pinia中的definestore函数即可,该函数族收两个参数:
import {defineStore} from 'pinia'
//第一个参敬是应用程序中store的唯一id,就是给数据仓库起个名字
//第二个参数是一个对象,store的配置项,比如配置store内的嫩据,修改数据的方法等等
export const useUsersStore = defineStore('user',{
//其他配置项
})
2.2.使用store
假如我们要在App.vue里面使用它,使用 store 很简单,直接引入我们声明的 useUsersStore 方法即可,我们可以先看一下执行方法输出的是什么:
<script setup lang="ts">
import { useUsersStore } from './store/user';
const store = useUsersStore();
console.log(store)
</script>
可以看到输出的是pinia里的一些方法
3.1.添加state
我们都知道store是用来存放公共数据的,我们利用defineStore函数创建了一个store,该函数第二个参数是一个options配置项,我们需要存放的数据就放在options对象中的state属性内。该属性就是用来存储数据的,我们往state中添加了3条数据。需要注意的是,state接收的是一个箭头函数返回的值,它不能直接接收一个对象。
import {defineStore} from 'pinia'
export const useUsersStore = defineStore('user',{
//这里的state与vue2中用来存放初始化变量的data的写法相似,需要return
state:()=>{
return {
name:"不知好歹",
age:20,
sex:"女",
items:[80,90]
}
},
})
3.2.操作state
3.2.1.读取state数据
我们往store里面存储数据就是为了操作它。首先我们读取一下它的数据,并让它在页面上显示,我们直接通过store.xxx的方式获取到了store存储的值,但是,这样比较繁琐,我们可以用解构的方式来获取值,使得代码更简洁一点。代码如下:
<template>
<p>姓名:{{ name }}</p>
<p>年龄:{{ age }}</p>
<p>性别:{{ sex }}</p>
</template>
<script setup lang="ts">
import { useUsersStore } from './store/user';
import {storeToRefs} from 'pinia'//响应式改变数据状态
const store = useUsersStore();
const {name,age,sex,items} = storeToRefs(store);
</script>
3.2.2. 多个组件使用state数据
我们使用store最重要的目的就是为了组件之间共享数据,那么接下来我们新建一个child.vue组件,在该组件内也使用state数据,跟App.vue几乎一样,代码如下:
<template>
<h1>我是Child组件</h1>
<p>姓名:{{ name }}</p>
<p>年龄:{{ age }}</p>
<p>性别:{{ sex }}</p>
</template>
<script setup lang="ts">
import { useUsersStore } from './store/user';
import {storeToRefs} from 'pinia'//响应式改变数据状态
const store = useUsersStore();
const {name,age,sex,items} = storeToRefs(store);
</script>
3.2.3. 修改、重置、批量修改以及替换state数据
想要修改store中的数据,可以直接重新赋值即可,重置只要调用store.$reset() 方法即可,而批量修改也有更简便的方法,使用store的patch()方法就行了,patch()有两种用法:①只传需要修改的数据就可以了,②可以使用patch的函数参数用法, 最后就是替换整个state,store.state(用的较少),利用pinia的storeToRefs函数,就可以将state中的数据变成响应式的,代码如下:
<template>
<p>姓名:{{ name }}</p>
<p>年龄:{{ age }}</p>
<p>性别:{{ sex }}</p>
<button @click="changeName">更改姓名</button>
<button @click="reset">重置state</button>
<button @click="patchStore">批量修改</button>
<button @click="thstore">替换store</button>
<!-- <child></child> -->
</template>
<script setup lang="ts">
// import child from './child.vue'
import { useUsersStore } from './store/user';
import {storeToRefs} from 'pinia'
const store = useUsersStore();
const {name,age,sex,items} = storeToRefs(store);
//更改state数据
const changeName = () =>{
store.name = "张三";
console.log(store)
}
//重置state
const reset =()=>{
store.$reset();
}
//批量修改store,传想要更改的数据就可以
const patchStore = () =>{
//普通用法
// store.$patch({
// name:"呜小游",
// age:27,
// })
//函数用法
store.$patch((state)=>{
state.name = '鹿小优'
state.items.push(100)
})
}
//替换state
const thstore = () => {
store.$state = {
name:"艾斯",
age:36,
sex:"男",
items:[666]
};
};
</script>
4.1.getters属性
getters是defineStore参数配置项里面的另一个属性,getter属性值是一个对象,该对象里面是各种各样的方法,跟Vue中的计算属性类似,它的作用就是返回一个新的结果。当然我们这里的getter就是处理state数据。
4.2.添加getter
我们在配置项参数中添加getter属性,我们在该属性对象中定义一个getAddAge方法,该方法会默认接收一个state参数,也就是state对象,然后该方法返回的是一个新的数据。代码如下:
import {defineStore} from 'pinia'
export const useUsersStore = defineStore('user',{
//这里的state与vue2中用来存放初始化变量的data的写法相似,需要return
state:()=>{
return {
name:"不知好歹",
age:20,
sex:"女",
items:[80,90]
}
},
getters:{
getAddAge:(state) =>{
return state.age + 80;
},
},
})
4.3. 使用getter
可以直接在标签上使用了store.gettAddAge方法,这样可以保证响应式,当我们点击修改数据按钮时,页面上的新的年龄字段也会跟着变化。代码如下:
4.4.getter中调用其它getter
我们再定义了一个名为getNameAndAge的getter函数,我们这里不使用箭头函数的形式,因为我们想在函数内部使用this,箭头函数的this指向问题相信大家都知道吧!所以这里没有采用箭头函数的形式。而是在函数内部直接使用this来获取state数据以及调用其它getter函数,这里this指向的是store实例,所以我们可以直接在getter方法中调用this。代码如下:
4.5.getter传参
既然getter函数做了一些计算或者处理,那么我们很可能会需要传递参数给getter函数,但是我们前面说getter函数就相当于store的计算属性,和vue的计算属性差不多,我们都知道Vue中计算属性是不能直接传递参数的,所以我们这里的getter函数如果要接受参数的话,也是需要做处理的。
5.1.actions属性
state和getters属性都主要是数据层面的,并没有具体的业务逻辑代码,它们两个和我们组件代码中的data数据和computed计算属性一样,如果我们有业务代码的话,最好就是写在actions属性里面,该属性和我们组件代码中的methods相似,用来放置一些处理业务逻辑的方法,actions属性同样是一个对象,该对象里面存储各种各样的方法,包括同步方法和异步方法。
5.2.添加actions
下面我们先定义一个简单的actions方法,跟state和getters是同级的,在实际场景中,该方法可以是任何逻辑,比如发送请求、存储token等等。把actions方法当作一个普通的方法即可,特殊之处在于该方法内部的this指向的是当前store。代码如下:
//actions相当于组件中的 methods,并且它们非常适合定义业务逻辑
//在action中同步和异步方法都可以使用。
actions:{
//同步方法设置name
saveName(name:string){
this.name = name;
},
getUser(){
return new Promise((resolve) => {
setTimeout(()=> {
resolve({
name: '苏小意',
age: 88
})
},2000)
})
},
//异步获取数据,输出user
async setUser() {
// const result = await getUser();
const result = await this.getUser();
console.log(result)
}
}
5.3.使用actions
使用actions中的方法也非常简单,比如我们在App.vue中想要调用该方法。代码如下:
总结
Pinia是Vuex的Plus版,Vue2和Vue3都支持,体积小,每个store都是独立管理,支持同步跟异步,Pinia的知识点较少,如果有Vuex基础,学起来更容易上手。我们更应该关注的是它的函数思想,我们在Vue3中的所有东西似乎都可以用一个函数来表示,pinia也是延续了这种思想。所以,理解这种Composition API的思想更重要,pinia无非就是以下3个大点:文章来源:https://www.toymoban.com/news/detail-428479.html
- state
- getters
- actions
以上就是pinia基础的使用,在实际工作中应该也能满足大部分需求了,如果还有兴趣学习pinia的其它特点,比如插件、订阅等等,可以到官网了解更多:https://pinia.web3doc.top/文章来源地址https://www.toymoban.com/news/detail-428479.html
到了这里,关于Pinia的基本使用的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!