vue状态管理器pinia、pinia-plugin-persist持久化储存
- 一、简介
- 二、配置状态管理器,需安装pinia、pinia-plugin-persist
- 三、定义store:defineStore
- 五、pinia中的Getter
- 六、pinia中的Action
- 七、pinia-plugin-persist持久化储存配置
一、简介
Pinia 是一个基于 Vue 3 的状态管理库,旨在简化和优化 Vue 应用程序的状态管理。它提供了一种简单且强大的方式来管理应用程序的状态,并且与 Vue 3 的响应性系统紧密集成。
以下是 Pinia 的一些特点和优势:
1.基于 Vue 3:Pinia 是专为 Vue 3 设计的状态管理库,充分利用了 Vue 3 的 Composition API 和响应性系统。
2.类型安全:Pinia 支持 TypeScript,并且在状态管理过程中提供了类型检查和推断,帮助开发者避免潜在的类型错误。
3.简单易用:Pinia 的 API 设计简洁清晰,使得状态管理变得简单且易于理解,同时提供了强大的功能。
4.零依赖:Pinia 本身没有任何依赖,因此可以轻松集成到现有的 Vue 3 项目中。
5.插件化:Pinia 支持插件系统,可以轻松扩展和定制状态管理的功能。
6.Devtools 支持:Pinia 与 Vue Devtools 集成良好,可以方便地在开发过程中调试和监控状态的变化。
二、配置状态管理器,需安装pinia、pinia-plugin-persist
1.pinia.js
import { createPinia } from "pinia";
import piniaPersist from "pinia-plugin-persist";
const pinia = createPinia();
pinia.use(piniaPersist); //使用持久化插件
export default pinia;
2.useDemoStore.js
import {defineStore} from "pinia";
const demoStore = defineStore('demoStore', {
state: () => ({
userId: '213213',
userName: '张三'
}),
actions: {//actions是store的方法methods
updateState(info){
this.$state = {
...this.$state,
...info
}
}
},
persist: {//pinia持久化配置,默认sessionStorage
enabled: true
}
});
export default demoStore
3.mian.js使用pinia插件
import { createApp } from "vue";
import App from "./App.vue";
import pinia from "@store/pinia.js";
const app = createApp(App);
app.use(pinia);
app.mount("#app");
4.使用store
<template>
<button @click="onUpdateStore">更新store</button>
<p>{{demoStore.userName}}</p>
</template>
<script setup>
import useDemoStore from "@store/useDemoStore.js";
const demoStore = useDemoStore();
const onUpdateStore = ()=>{
demoStore.updateState({userId: 'wqewqe', userName: '李四'})
}
</script>
三、定义store:defineStore
1.Option Store:defineStore(idid,options),options配置如下
- id:用于在整个应用程序中标识存储的唯一字符串键,等同于参数id,options传id,参数id可不用传
- state:创建新状态的函数。必须是箭头函数以确保正确的类型。
- getters:可选的获取器对象,每个获取器函数都有一个state参数
- actions:可选的操作对象
- hydrate:允许在 SSR 期间对存储进行水合处理,当在存储定义中使用复杂状态(例如仅客户端引用)时,并且从 pinia.state 复制值不足以满足需求时。
- options配置除了上述配置,还可配置插件的配置,如:pinia-plugin-persist持久化储存
import {defineStore} from "pinia";
const demoStore = defineStore('demoStore', {
state: () => ({
userId: '213213',
userName: '张三'
}),
actions: {//actions是store的方法methods
updateState(info){
this.$state = {
...this.$state,
...info
}
}
},
persist: {//pinia持久化配置,默认sessionStorage
enabled: true
}
});
export default demoStore
2.Setup Store:defineStore(stoireName,setup,options),options配置如下:
- actions:可选的操作对象
- options配置除了上述配置,还可配置插件的配置,如:pinia-plugin-persist持久化储存
const demoStore = defineStore('counter', () => {
const state = ref({
userId: '213213',
userName: '张三'
});
const updateState = (info) => {
state.value = {
...state.value,
...info
}
}
return {state, updateState}
},{
persist: {//pinia持久化配置,默认sessionStorage
enabled: true
}
})
export default demoStore
3.defineStore除了会返回state、getters、actions等配置,还会返回以下属性:
- store.$id:储存store的key
- store.$state:state数据
- store.$reset():重置store
- store.$patch(state):更新store
- store.$subscribe((mutation, state)=>{}):订阅store
- store.$dispose():用于销毁存储实例并清理其内部状态。当你不再需要某个存储实例时,可以调用该方法来手动触发清理操作,以释放资源并避免内存泄漏
- store.$onAction((store,name,args, after, onError)=>{}, detached):action监听器,当一个 action 即将被调用时,callback会触发,返回一个删除监听器的函数,detached组件销毁时是否保留监听器
四、pinia中的State
在 Pinia 中,state 是存储实例中保存数据的部分。它代表存储的状态,可以包含应用程序中需要共享和管理的数据。在定义 Pinia 存储时,可以通过 state 选项指定一个函数,该函数返回存储的初始状态。
state 函数应该返回一个对象,该对象包含存储实例的初始状态数据。这些数据可以是任何类型,例如基本数据类型、对象、数组等。通过在 state 函数中返回这些数据,Pinia 将使用它们作为存储实例的初始状态,并在需要时对其进行响应式处理,以确保状态的变化能够正确地触发应用程序的重新渲染。
通过在存储定义中设置 state,可以轻松地定义和管理存储实例的初始状态,从而构建具有响应式状态管理的应用程序。
1.定义state,为了完整类型推理,推荐使用箭头函数
import { defineStore } from 'pinia'
const useStore = defineStore('storeId', {
state: () => {
return {
// 所有这些属性都将自动推断出它们的类型
count: 0,
name: 'Eduardo',
isAdmin: true,
items: [],
hasChanged: true,
}
},
})
2.访问 state,响应式访问state可使用storeToRefs,注意:使用storeToRefs时一定要解构,否则使用时,字符串会多出双引号
const store = useStore()
// count是响应式的 ref
// 同时通过插件添加的属性也会被提取为 ref
// 并且会跳过所有的 action 或非响应式 (不是 ref 或 reactive) 的属性
const {count} = storeToRefs(store());
store.count++
3.重置 state
const store = useStore()
store.$reset()
4.变更 state
const store = useStore()
store.$patch({
count: store.count + 1,
age: 120,
name: 'DIO',
})
5.订阅 state
const store = useStore()
store.$subscribe((mutation, state) => {
// import { MutationType } from 'pinia'
mutation.type // 'direct' | 'patch object' | 'patch function'
// 和 cartStore.$id 一样
mutation.storeId // 'cart'
// 只有 mutation.type === 'patch object'的情况下才可用
mutation.payload // 传递给 cartStore.$patch() 的补丁对象。
// 每当状态发生变化时,将整个 state 持久化到本地存储。
localStorage.setItem('cart', JSON.stringify(state))
})
五、pinia中的Getter
在 Pinia 中,getter 是一种用于从存储实例中获取数据的方法。Getter 允许你定义一些计算属性,这些属性可以根据存储实例的状态数据进行计算,并返回相应的结果。通过使用 Getter,可以将一些复杂的逻辑封装在存储实例中,以便在需要时轻松获取计算得到的值。
在定义 Pinia 存储时,你可以通过 getters 选项指定一个包含 Getter 函数的对象。每个 Getter 函数都可以访问存储实例的状态数据,并根据需要执行计算。Getter 函数不会直接修改存储的状态,而是用于派生或计算新的数据。
通过使用 Getter,你可以在存储实例中实现一些复杂的数据逻辑,例如对状态数据进行过滤、排序、映射等操作,从而提供更丰富和灵活的数据访问方式。Getter 的值可以通过在组件中访问存储实例的方式来获取,从而实现对计算属性的使用和响应式更新。
1.定义Getter
export const useCounterStore = defineStore('counter', {
state: () => ({
count: 0,
}),
getters: {
doubleCount: (state) => state.count * 2,
doubleCountPlusOne() { ✨
return this.doubleCount + 1
},
},
})
2.getter 传递参数,getter 是计算属性不能传递参数,可以从 getter 返回一个函数,该函数可以接受任意参数
export const useUserListStore = defineStore('userList', {
getters: {
getUserById: (state) => {
return (userId) => state.users.find((user) => user.id === userId)
},
},
})
3.访问其他 store 的 getter,直接调用其他store使用getter即可
import { useOtherStore } from './other-store'
export const useStore = defineStore('main', {
state: () => ({
count: 0
}),
getters: {
otherGetter(state) {
const otherStore = useOtherStore()
return state.localData + otherStore.data
},
},
})
六、pinia中的Action
在 Pinia 中,Action 是一种用于执行异步操作或对存储状态进行修改的方法。Actions 允许在存储实例中定义一些操作,这些操作可以触发状态的变化,并且可以包含异步逻辑,如网络请求、定时器等。通过使用 Actions,可以将数据修改逻辑封装在存储实例中,使应用程序的状态管理更加清晰和可维护。
在定义 Pinia 存储时,可以通过 actions 选项指定一个包含 Action 函数的对象。每个 Action 函数可以接受参数,并且通常会执行一些异步操作,如发起网络请求或执行耗时计算。在 Action 函数中,你可以访问存储实例的状态数据,并根据需要修改这些数据。
Actions 可以被组件调用,从而触发相应的操作。在 Action 函数中,可以通过调用 this 对象来访问存储实例的方法和属性,以便在操作中使用存储的状态数据,并在操作完成后更新状态。Actions 的执行是异步的,因此可以处理需要时间的操作,而不会阻塞应用程序的主线程。
通过使用 Actions,你可以将数据修改逻辑和异步操作集中在存储实例中,使得应用程序的状态管理更加模块化和可测试。
1.定义action
export const useCounterStore = defineStore('main', {
state: () => ({
count: 0,
}),
actions: {
increment() {
this.count++
},
randomizeCounter() {
this.count = Math.round(100 * Math.random())
},
},
})
2.访问其他 store 的 action,同getter一样直接调用其他store使用action即可
import { useAuthStore } from './auth-store'
export const useSettingsStore = defineStore('settings', {
state: () => ({
preferences: null,
}),
actions: {
async fetchUserPreferences() {
const auth = useAuthStore()
if (auth.isAuthenticated) {
this.preferences = await fetchPreferences()
} else {
throw new Error('User must be authenticated')
}
},
},
})
3.订阅 action
const unsubscribe = someStore.$onAction(
({
name, // action 名称
store, // store 实例,类似 `someStore`
args, // 传递给 action 的参数数组
after, // 在 action 返回或解决后的钩子
onError, // action 抛出或拒绝的钩子
}) => {
// 为这个特定的 action 调用提供一个共享变量
const startTime = Date.now()
// 这将在执行 "store "的 action 之前触发。
console.log(`Start "${name}" with params [${args.join(', ')}].`)
// 这将在 action 成功并完全运行后触发。
// 它等待着任何返回的 promise
after((result) => {
console.log(
`Finished "${name}" after ${
Date.now() - startTime
}ms.\nResult: ${result}.`
)
})
// 如果 action 抛出或返回一个拒绝的 promise,这将触发
onError((error) => {
console.warn(
`Failed "${name}" after ${Date.now() - startTime}ms.\nError: ${error}.`
)
})
}
)
// 手动删除监听器
unsubscribe()
七、pinia-plugin-persist持久化储存配置
1.使用持久化存储插件
import { createPinia } from "pinia";
import piniaPersist from "pinia-plugin-persist";
const pinia = createPinia();
pinia.use(piniaPersist); //使用持久化插件
export default pinia;
2.持久化存储配置,defineStore时增加persist配置
import {defineStore} from "pinia";
const demoStore = defineStore('demoStore', {
state: () => ({
userId: '213213',
userName: '张三'
}),
persist: {//pinia持久化配置,默认sessionStorage
enabled: true
}
});
export default demoStore
3.持久化储存配置项
- enabled:是否启用持久化村村
- strategies:配置策略
4.配置策略之自定义储存,自定义储存key,并且使用localStorage储存
import {defineStore} from "pinia";
const demoStore = defineStore('demoStore', {
state: () => ({
userId: '213213',
userName: '张三'
}),
actions: {//actions是store的方法methods
updateState(info) {
this.$state = {
...this.$state,
...info
}
}
},
persist: {//pinia持久化配置,默认sessionStorage
enabled: true,
strategies: [{
key:'demo',
storage: localStorage
}]
}
});
export default demoStore
5.配置策略之不同的状态使用不同的储存方式,如下代码:userId使用sessionStorage,userName使用localStorage
import {defineStore} from "pinia";
const demoStore = defineStore('demoStore', {
state: () => ({
userId: '213213',
userName: '张三'
}),
actions: {//actions是store的方法methods
updateState(info) {
this.$state = {
...this.$state,
...info
}
}
},
persist: {//pinia持久化配置,默认sessionStorage
enabled: true,
strategies: [{
storage: sessionStorage,
paths: ['userId']
}, {
storage: localStorage,
paths: ['userName']
}]
}
});
export default demoStore
6.配置策略之定制存储
import Cookies from 'js-cookie'
const cookiesStorage = {
setItem (key, state) {
return Cookies.set('accessToken', state.accessToken, { expires: 3 })
},
getItem (key) {
return JSON.stringify({
accessToken: Cookies.getJSON('accessToken'),
})
},
}
export const useUserStore = defineStore('storeUser', {
state () {
return {
firstName: 'S',
lastName: 'L',
accessToken: 'xxxxxxxxxxxxx',
}
},
persist: {
enabled: true,
strategies: [
{
storage: cookiesStorage,
paths: ['accessToken']
},
],
},
})