pinia学习笔记

335 阅读6分钟

一:为什么要使用 Pinia?

Pinia 是 Vue 的存储库,它允许您跨组件/页面共享状态。

  1. 可以对Vue2和Vue3做到很好的支持,也就是老项目也可以使用Pinia。
  2. 抛弃了Mutations的操作,只有state、getters和actions.极大的简化了状态管理库的使用,让代码编写更加容易直观。
  3. 不需要嵌套模块,符合Vue3的Composition api ,让代码更加扁平化。
  4. 完整的TypeScript支持。Vue3版本的一大优势就是对TypeScript的支持,所以Pinia也做到了完整的支持。如果你对Vuex很熟悉的话,一定知道Vuex对TS的语法支持不是完整的
  5. 代码更加简洁,可以实现很好的代码自动分割。Vue2的时代,写代码需要来回翻滚屏幕屏幕找变量,非常的麻烦,Vue3的Composition api完美了解决这个问题。 可以实现代码自动分割,pinia也同样继承了这个优点。

二:Pinia开发环境安装

1.使用Vite就需要先初始化vite:npm init vite@latest
2.启动项目:

npm install
npm run dev

3.pinia的安装npm install pinia

image.png

三:用Pinia的方式创建一个store

1.在main.ts文件里引入Pinia

import { createPinia } from 'pinia'

引入后,通过createPinia( )方法,得到pinia的实例,然后将Pinia挂载到Vue根实例上。

image.png

2.创建store状态管理库

直接在/src目录下,新建一个store文件夹。有了文件夹之后,再创建一个index.ts文件。 这个文件里的代码,我们一般只做三件事:

  1. 定义状态容器(仓库)
  2. 修改容器(仓库)中的 state
  3. 仓库中的 action 的使用

第一步:定义状态容器(仓库)

image.png

1 . defineStore( ) 方法的第一个参数:相当于为容器起一个名字。注意:这里的名字必须唯一,不能重复。
2 . defineStore( ) 方法的第二个参数:可以简单理解为一个配置对象,里边是对容器仓库的配置说明。当然这种说明是以对象的形式。
3. state 属性: 用来存储全局的状态的,这里边定义的,就可以是为SPA里全局的状态了。
4. getters属性: 用来监视或者说是计算状态的变化的,有缓存的功能。
5. actions属性: 对state里数据变化的业务逻辑,需求不同,编写逻辑不同。说白了就是修改state全局状态数据的。

第二步:我们在Store里定义一个State,我们这里就写Hello Pinia!。

image.png这时候这个helloPinia就是全局的状态数据,是每个页面和组件都可以通过Pinia方法读取到的。

3.在vue3组件里读取Store数据

在\src\components里,新建一个Hyy.vue的组件。代码如下: 先引入mainStore,然后通过mainStore得到store实例,就可以在组件里调用store里的state定义的状态数据了

image.png写好这个组件后,到App.vue里引入,就可以使用了:

image.png

四:Pinia改变状态数据和注意事项

1.新建组件,实现状态数据的改变

为了演示数据仓库的概念,新建一个组件。然后在一个组件里修改状态数据,看看另一个组件中的数据是否会改变

在\components\文件夹下新建一个文件CountButton.vue

image.png 因为这里要做的是一个可以计数的组件,所以先到\store\index.ts的state属性中,增加一个状态数据count : 0。

image.png

有了这个状态数据后,再回到\components\CountButton.vue文件里,增加button和对应的业务逻辑(注意这里的业务逻辑就是修改状态数据)。代码如下:

image.png

写好后,我们把count显示在Hyy.vue组件里。

image.png

然后把CountButton加入到App.vue页面中。

image.png

五:Pinia修改状态数据的多种方式

使用$patch修改多条数据

接着上面编写的CountButton.vue 组件,我们再编写一个方法handleClickPatch( )这个方法。我们采用Pinia中的$patch的方式编写。

image.png然后在里添加一个按钮,点击后执行这个方法。

image.png

当然我在修改单条数据的时候,我喜欢这种直接修改的方式store.count++,因为足够简单。但是如果你同时修改多条数据,这里建议你使用$patch的方法。

比如现在我们点击按钮时,同时修改状态数据helloPinia,就可以写成这种方式:

image.png

那你说我在handleClick里直接写两行代码,是不是也可以实现这样的效果。通过代码测试,是可以实现的。那为什么还要用$patch来做?

image.png

因为Pinia的官方网站,已经明确表示patch的方式是经过优化的,会加快修改速度,对程序的性能有很大的好处。所以如果你是多条数据同时更新状态数据,推荐使用 patch的方式是经过优化的,会加快修改速度,对程序的性能有很大的好处。所以如果你是多条数据同时更新状态数据,推荐使用patch方式更新。

完整代码:

image.png

$patch加函数的形式修改状态数据

上面的$patch方法,我们的参数使用的是一个对象。还有一种方式是传递函数,这种方法适合复杂数据的修改,比如数组、对象的修改。

再编写一个方法handleClickMethod( ),然后传递一个箭头函数进去。

image.png 这时候的state就是store仓库里的state,所以我们可以直接在函数里改变任何状态数据的值。为了看到效果,我们再编写一个按钮,来执行这个方法。

image.png

在actions中写好逻辑,再调用actions

如果你有一个修改的过程非常复杂,你可以先在store里,定义好actions中的函数,然后在组件里再调用函数。

我们先到\src\store\index.ts文件里,在actions的地方编写一个changeState( )方法,用来改变数据状态。代码如下:

image.png 有了这个changeState( )函数后,就可以在组件中调用这个函数来修改状态数据了。
来到\src\components\CountButton.vue文件。编写一个新的方法handleClickActions( )方法。然后就可以用store调用changeState( )方法了。

image.png然后再加入一个按钮,调用这个方法就可以了。

image.png 注意: 在用actions的时候,不能使用箭头函数,因为箭头函数绑定是外部的this。

六:Pinia中的Getters使用

1. 新增状态属性和编写Getters

先在\src\store\index.ts文件的state里增加一个phone的状态数据。

image.png 然后在getters里编写一个方法,这个方法就是隐藏手机号中间四位的,隐藏的方法就是使用正则表达式替换。代码如下:

image.png 然后到\src\components\Hyy.vue中直接显示隐藏号码显示:

image.png

3. 关于this的使用

在getters里可以用this进行操作

image.png

因为我们使用的是TS,所以如果我们不传state, TypeScript是无法自动推导出来返回的数据类型的,所以这里我们要标明返回类型为String。就不会提示错误了。

七:Pinia中Store的互相调用

在上面代码中我们一直只使用了一个Store仓库,在真实项目中我们往往是有多个Store的。有多个Stroe时,就会涉及Store内部的互相调用问题。

  1. 第一步:新建一个Store仓库

在\src\store下新建一个Hyy.ts文件:

image.png 这是一个非常简单的仓库,只有state(状态数据),需要注意的是ID要是唯一的。有了这个仓库后,就可以回到index.ts这个仓库中调用了。

  1. 第二步:先引入Hyy这个store。

image.png 3. 第三步:然后在actions部分加一个getList( )方法。 这部分就写的很简单了,只是用console.log( )打印到控制台 上就可以了。

image.png\src\store\index.ts的全部代码:

image.png 这样就实现了两个store中互相调用。 4. 第四步:为了看到效果,我们依然来到\src\components\CountButton.vue这个文件里,写一个新的方法,就叫做getList( )。

image.png有了getList( )方法后,在template部分,写一个按钮进行触发。

image.png到浏览器中查看效果,按F12打开控制台,点击按钮后,可以看到跨Store的状态数据调用已经成功了。