Pinia状态管理

Pinia状态管理

1.Pinia的简介

Pinia是Vue生态中Vuex的代替者,是一个全新的Vue状态管理库。对比Vuex来说,Pinia有五大优势:

  1. 对Vue2、Vue3都支持
  2. 抛弃了Mutations操作,只有state、getters和actions,极大简化了状态管理库的使用,让代码编写更加容易直观
  3. 不需要嵌套模块,符合Vue3的Composition API
  4. 完整的TypeScript支持
  5. 代码更加简洁

2.Pinia的基本使用

首先需要安装pinia,只需要简单执行下面命令即可。

1
npm install pinia

之后我们需要在main.ts中进行引入,并进行挂载,下面是main.ts的全部内容

1
2
3
4
5
6
7
8
9
10
11
12
13
import {createApp} from 'vue'
import App from './App.vue'
import {createPinia} from "pinia"

import './assets/main.css'

// 创建pinia实例
const pinia = createPinia()
const app = createApp(App)

// 进行挂载
app.use(pinia)
app.mount('#app')

3.store状态管理库的创建

/src目录下新建store文件夹,再创建一个index.ts文件,在这个文件中,主要完成状态容器的定义,修改容器中的state和仓库中action的使用。该文件的内容基本固定,如下:

1
2
3
4
5
6
7
8
9
10
11
import {defineStore} from 'pinia'

export const mainStore = defineStore('main', {
state: () => {
return {
info: 'I am Info'
}
},
getters: {},
actions: {}
})
  • state:用来存储全局的状态,其中状态的创建与组件中的data类似,
  • getters:在获取状态的时候进行某种处理
  • actions:用来修改state全局状态数据

4.store数据的读取

定义了store状态之后,我们就可以在组件中读取对应的数据。先引入mainStore,然后在setup阶段通过mainStore得到store实例,之后就可以在组件里调用store里state定义的状态数据了,代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<template>
<div>
I am Test
<h2>{{ store.info }}</h2>
</div>
</template>

<script>
import {mainStore} from "@/store"

export default {
name: "Test",
setup() {
const store = mainStore()

return {
// 您可以返回整个 store 实例以在模板中使用它
store,
}
},

}
</script>

5.改变状态数据

在Pinia中修改状态数据有多种方式。后续的举例代码中,对state进行操作,所以这里先明确目前state中含有的参数:

1
2
3
4
5
6
7
state: () => {
return {
info: 'I am Info',
count: 1,
count1: 1,
}
},

第一种方式和函数操作类似,直接在函数逻辑中操作即可。下面的操作就是在一个函数中对store中的数据进行操作:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import {mainStore} from "@/store";

export default {
name: "MyButton",
setup() {
const store = mainStore()

return {
store,
}
},
methods:{
add(){
this.store.count++;
}
}
}

第二种方式是使用Pinia中的$patch方式,同样是写在method中,但是调用$patch方式。Pinia 的官方网站,已经明确表示$patch的方式是经过优化的,会加快修改速度,对程序的性能有很大的好处。所以如果是多条数据同时更新状态数据,推荐使用$patch方式更新。

1
2
3
4
5
6
7
8
methods: {
add1() {
this.store.$patch({
count: this.store.count + 1,
count1: this.store.count1 + 2,
})
}
}

第三种方式也是使用$patch,上面的操作是传入一个对象,第三种方式是传入一个函数。传入函数的方式适合复杂逻辑的修改。

1
2
3
4
5
6
7
8
9
10
methods: {
add2() {
this.store.$patch((state) => {
state.count++
if (state.info === "I am Info") {
state.info = "I am not Info"
}
})
}
}

第四种方式是在actions中写好修改逻辑,然后再调用actions。如果一个修改的过程非常复杂,可以先定义好actions中的函数,然后在组件里调用函数。如下过程所示。

首先在/src/store/index.ts中的actions编写一个changeState()方法(方法名任意),用来改变数据状态,代码如下:

1
2
3
4
5
6
actions: {
changeState(){
this.count++
this.info = 'I am really Info'
}
}

之后在相关组件的method中进行调用:

1
2
3
4
5
methods: {
add3(){
this.store.changeState();
}
}

6.Pinia中getters的使用

Pinia中的getters和Vue中的计算属性类似,就是在获取State的值的时候做一些额外的处理。类似下面的代码逻辑。我们首先在getters中定义下面的修改方法,就是在info后面直接加上haha:

1
2
3
4
5
getters: {
hahaInfo(state){
return state.info + "haha"
}
}

定义之后,可以直接像使用普通属性一样使用,使用插值表达式{{state.hahInfo}}就可以直接显示在页面上。

getters是具有缓存特性的。我们可以在其中的方法里面增加一个console.log进行输出,多次调用这个值,只会输出一次。

在上面的使用中我们是传入了一个state,当然也可以使用this。如果使用的是TypeScript,不传state,它无法自动推导出返回类型,这里标明返回类型即可。

1
2
3
4
5
getters: {
hahaInfo(): String {
return this.info + "haha"
}
}

7.分文件的状态管理

在上面的例子中,我们都是使用store目录下的index.ts进行说明的。而实际上我们也可以在store目录下创建更多的ts文件,来分文件进行全局状态管理。这样更有效果。例如我们可以创建store/counter.ts,其中的内容定义与使用大体相同,只是在引用的时候需要如下使用。而只写这个@/store目录的话,则是去访问index.ts

1
2
3
4
5
6
7
8
9
10
11
12
13
// store/counter.ts
import { ref, computed } from 'vue'
import { defineStore } from 'pinia'

export const useCounterStore = defineStore('counter', () => {
const count = ref(0)
const doubleCount = computed(() => count.value * 2)
function increment() {
count.value++
}

return { count, doubleCount, increment }
})

下面是使用方式:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// usage
import { useCounterStore } from '@/stores/counter'

export default {
setup() {
const counter = useCounterStore()

counter.count++
// 带自动补全
counter.$patch({ count: counter.count + 1 })
// 或使用 action 代替
counter.increment()

return {
counter
}
},
}

参考文章

  1. 介绍 | Pinia 中文文档 (web3doc.top)
  2. 技术胖-Pinia入门视频教程 全新一代状态管理工具Pinia -Vue3全家桶系列 (jspang.com)

Pinia状态管理
http://example.com/2022/07/20/Pinia状态管理/
作者
EverNorif
发布于
2022年7月20日
许可协议