状态管理Pinia
在学习 vue3.x 时,看官方文档上极力推荐 Pinia,更强大,功能更丰富,因此也学习了一下,使用过后发现确实比 vuex 精简了许多。
对比了下,发现 Pinia 和 vuex 使用上还是挺相似的:
相同点:都有 state、actions、getters,都是在 actions 中操作 state。
不同点:Pinia 中没有 mutations,Pinia 中在 actions 中操作 state,是直接通过 this 访问相应状态来进行更改。
# 1、安装 pinia
npm install pinia
# 2、创建 pinia 并将其传递给根应用程序(在 main.ts 中):
import { createPinia } from 'pinia';
app.use(createPinia());
2
3
# 3、在 src 文件夹下新建 pinia 文件夹(名字可随意), 在该文件夹下新建 store.ts(例子是使用 ts 的,如果没有使用 ts 则直接 store.js 即可,名字随意)。代码如下:
import { defineStore } from "pinia"
import localstore from "@/utils/localstoreUtils" // 对localStorage进行了封装
export const useStore = defineStore({
id: 'globalState',
state: () => ({
name: '张三',
age: 34
}),
actions: {
changeInfo (payload: {name: string, age: number}) {
this.name = payload.name
this.age = payload.age
localstore.setItem('userInfo', JSON.stringify(payload))
}
},
getters: {
getInfo (state) {
const infoStr = localstore.getItem('userInfo') ? JSON.parse(localstore.getItem('userInfo')) : ""
if (infoStr) {
return {
name: infoStr.name,
age: infoStr.age
}
} else {
return state
}
}
}
})
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
# 4、这样就可以在项目其他地方进行使用,如新建 Pinia.vue 文件,代码如下:
<template>
<div class="wrapper">
Pinia学习
<p>姓名:{{info.name}}</p>
<p>年龄:{{info.age}}</p>
<button @click="handleChange">更改信息</button>
</div>
</template>
<script setup lang="ts">
import { computed } from 'vue'
import { useStore } from '@/pinia/store'
const store = useStore()
const info = computed(() => {
return store.getInfo
})
function handleChange () {
store.changeInfo({ name: '李四', age: 45 })
}
</script>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
也可以通过
$patch + 对象
$patch + 函数:通过函数方式去使用的时候,函数接受一个 state 的参数,state 就是 store 仓库中的 state
store.$patch({name: '王五', age: 55})
或者
store.$patch((state) => {
state.name = "赵六"
state.age = 37
})
2
3
4
5
6
7
8
9
ps:上述 getInfo 对应了 store.ts 中 getters 中的 getInfo 方法,changeInfo 对应了 actions 中的 changeInfo 方法。
如果需要进行异步操作的话,还是跟使用 vuex 一样,在 actions 中的方法里进行。
pinia 解构不具有响应式,可以使用 storeToRefs 解决,例如:
import { storeToRefs } from 'pinia'
import { useStore } from '@/pinia/store'
const store = useStore()
const { name, age } = storeToRefs(store)
2
3
4
数据持久化插件:pinia-plugin-persistedstate
安装:
npm install pinia-plugin-persistedstate
vue3 中使用:
在 main.js(或 main.ts)中增加如下代码:
import { createPinia } from 'pinia'
import piniaPersist from 'pinia-plugin-persistedstate'
const pinia = createPinia()
pinia.use(piniaPersist)
createApp({}).use(pinia).mount('#app')
2
3
4
5
6
在需要用到的地方使用:
import { defineStore } from 'pinia'
export const useUserStore = defineStore({
id: 'userStore',
state () {
return {
name: '张三',
age: 23
}
},
persist: true
})
2
3
4
5
6
7
8
9
10
11
以上为 true 表示开启了数据持久化,默认使用 localStorage,且缓存该 store 中的所有数据,如果想使用 sessionStorage 或者指定需要缓存的数据,更多配置如下:
import { defineStore } from 'pinia'
export const useUserStore = defineStore({
id: 'userStore',
state () {
return {
name: '张三',
age: 23
}
},
persist: {
key: 'userStore',
storage: sessionStorage,
path: ['age']
}
})
2
3
4
5
6
7
8
9
10
11
12
13
14
15
ps:persist 是一个对象时,里面有 key,storage 和 path 三个字段。
其中 key 表示设置缓存 sessionStorage 或 localStorage 时的 key,如果没有设置该 key,则默认使用上面那个 id 值。
storage 可设置为 sessionStorage 或 localStorage,或者自定义 storage。
path 是一个数组,用来定义需要持久化的数据,如果没有定义 path,则缓存所有数据