本文超详细讲解了 vue3+pinia+自动持久化插件+自定义存储器对象实现状态数据持久化 的配置和代码实现,会不会详细得令人发指😄😄😄!
之前在 vue2 版本中,普遍都是使用 vuex 插件和手写操作 localStorage 或 sessionStorage 的 actions 方法对应用中组件间的共享数据(状态)进行管理。
由于 vuex 比较臃肿,并且对 TS 支持不够好,vue3 中改为普遍使用 pinia 这个轻量级的状态数据管理插件,该插件也是官方在 vuex 的基础进行优化和修改的,区别是更轻量,性能更好,对 TS 语法的支持较好,并且去除了多余的 Mutations 配置项,直接例用 actions 配置项配置操作 state 数据的方法即可!
例用 pinia 插件 + 数据持久化插件 pinia-plugin-persistedstate,可以在应用运行中自动持久化 pinia store state 中的数据到浏览器自带本地存储 window.localStorage 和 window.sessionStorage (这两个本地存储器是数据持久化插件 pinia-plugin-persistedstate默认自带支持的),及支持自定义存储器对象,比如本例自定义了一个 cookie 的存储器对象 cookieStorage。
话不多说,直接入正题!
以下是配置部分:
1、安装所需插件包:pinia、pinia-plugin-persistedstate、js-cookie
npm i pinia pinia-plugin-persistedstate js-cookie
2、在 ./src/store 目录下创建 cookieStorage.js 存储器对象:
// cookieStorage.js
/**
* 为 pinia-plugin-persistedstate 插件自定义 storage 存储器对象 cookieStorage,
* 自定义存储器对象,必须按以下要求实现 setItem 和 getItem 方法,并且在这两个方法调用设置/读取 cookie 等
* 本地存储的方法必须是同步的,不能是异步的,
* 这里使用 js-cookie 第三方 cookie 操作包实现自定义 storage 存储器对象 cookieStorage
*/
import Cookie from 'js-cookie'
export const cookieStorage = {
// 参数 key 为 userStore.js 中 persist 配置项中保存到 storage 存储中的 key 键名
// 参数 state 为 userStore.js 中 persist 配置项中要持久化到 storage 的 state 属性名,不是全部 state
setItem(key, state) {
// console.log('cookieStorage setItem state:', state)
// js-cookie 包 setItem 方法的第三个参数配置对象解释:
// expires: 为数字时表示过期天数,缺少该参数,表示仅会话期间有效,支持 new Date 对象及其字符串格式
// path:默认值为/,表示全站点所有路径页面可操作该 cookie,为 '' 空值表示仅当前页面可操作该 cookie
// domain:缺省该参数默认值为当前域名及其子域名可操作该 cookie
// return Cookie.setItem(key, state, { expires: 9999, path: '/', domain: '' })
return Cookie.set(key, state)
},
getItem(key) { // 首次自动加载这个自定义cookie存储器时, getItem 方法比 setItem 方法先执行
// console.log('cookieStorage getItem:', key, Cookie.get(key))
let value = Cookie.get(key) || '{}'
// js-cookie 工具包 get 方法返回字符串,而 vue-cookies 工具包则返回对象
value = typeof value == 'object' ? value : JSON.parse(value)
// 存储器的这个 getItem 方法需返回字符串
return JSON.stringify(value)
}
}
3、在 ./src/store 目录下创建 userStore.js 操作用户 state 状态数据及方法的 store 模块:
// userStore.js
import { defineStore } from 'pinia'
import { cookieStorage } from '@/store/cookieStorage.js'
/**
* 在其它页面组件中通过以下方法:
* import useUserStore from '@/store/userStore.js'
* const userStore = useUserStore()
* 加载此 userStore 模块后,通过如下方法操作 store
* 1、通过如下方法读取/设置 state 数据
* userStore.user = {xx: 'yy'}
* 同时设置多个 state 数据方法一(对象参数式):
* userStore.$patch({user: {}, age: 20})
* 同时设置多个 state 数据方法二(回调函数式,推荐此方法高性能):
* userStore.$patch( (state) => {
* state.user = {}
* age = 20
* })
* 2、订阅(捕获) state 修改
* userStore.$subscribe((mutation, state)
* 3、订阅(捕获) actions 函数调用
* userStore.$onAction(callback, true) // 参数二 true,表示组件 unmount 后,仍有效,缺省,组件销毁,订阅事件也销毁
* 4、手动取消订阅 actions
* const unsubscribe = someStore.$onAction(callback)
* unsubscribe()
* 5、可在任意组件中通过 userStore.$hydrate() 方法手动提取保存在 storage 中的数据,应用首次运行时,会自动提取一次
* 6、应用在运行或刷新页面后,会自动将 store state 中的数据持久化到 storage,也可通过 userStore.$persist() 方法手动持久化,
* 当修改或通过 actions 修改 state 的数据,才会自动持久化到 storage
* 更多详细说明见 pinia 官网:https://pinia.vuejs.org/core-concepts/actions.html
*/
export const useUserStore = defineStore('userStore', {
// 状态数据
state: () => ({
user: {},
}),
// getters 定义
geters: {},
// actions 定义
actions: {},
// 自动持久化插件 pinia-plugin-persistedstate 的配置部分,配置单存储对象,用{}即可,多个用数组[]配置
persist: [
// sessionStorage 存储配置部分
{
// 使用 sessionStorage 本地存储
storage: window.sessionStorage,
// 保存到 storage 中数据的 key 键名
key: 'userInfo',
// 指定要保存 state 中哪些数据到 storage,默认值为 undefined,和 null 一样默认保存 state 中所有数据,
// 使用数组指定要保存到 storage 中的数据,如 ['user'],或 ['user.userId'],空数组 [] 表示不保存任何数据,但会自动提取所有数据
paths: null,
// 插件在默认自动提取或通过 userStore.$hydrate() 手动拉取 storage 中的数据前,自动触发该回调函数,
// ctx 是该插件的上下文对象,包括 pinia 实例、该 store 的 state/getters/actions 信息、
// 和 main.js 里挂载的整个应用的 app 实例信息,beforeRestore 该回调方法在 useUserStore() 方法之前调用,
// userStore.$hydrate({runHooks: false}),手动提取 store 数据时,加上 {runHooks: false} 参数后,
// 不会触发 beforeRestore 和 beforeRestore 回调函数
/* beforeRestore: (ctx) => {
console.log('piniaPlugPersistedstate beforeRestore ctx:', ctx)
}, */
// 插件在默认自动提取或通过 userStore.$hydrate() 手动拉取 storage 中的数据后,自动触发该回调函数,
// ctx 是该插件的上下文对象,包括 pinia 实例、该 store 的 state/getters/actions 信息、
// 和 main.js 里挂载的整个应用的 app 实例信息,afterRestore 该回调方法在 useUserStore() 方法之前调用,
// userStore.$hydrate({runHooks: false}),手动提取 store 数据时,加上 {runHooks: false} 参数后,
// 不会触发 beforeRestore 和 beforeRestore 回调函数
/* afterRestore: (ctx) => {
console.log('piniaPlugPersistedstate afterRestore ctx:', ctx)
}, */
// 调试开关,默认值 false。设为 true ,会自动在持久化或提取数据时发生的错误,通过控制台 console.error()打印出来
debug: true
},
// cookieStorage 存储配置部分
{
storage: cookieStorage,
key: 'userInfo',
paths: undefined,
debug: true
}
]
})
4、在 main.js 中导入和注册 pinia 插件和数据持久化插件 pinia-plugin-persistedstate
// main.js
import { createApp } from 'vue'
import App from './App.vue'
const app = createApp(App)
import { createPinia } from 'pinia'
const pinia = createPinia()
import piniaPersistedState from 'pinia-plugin-persistedstate'
pinia.use(piniaPersistedState)
app.use(pinia)
app.mount('#app')
5、新建 Test.vue 测试 pinia 状态数据及自动持久化操作
// Test.vue
<template>
<div>
<div>userStore的数据是(初始化为空):{{ user }}</div>
<button @click="chgUserData">修改 userStore 数据</button>
</div>
</template>
<script setup>
// 导入 pinia 配置的 userStore
import { useUserStore } from '@/store/userStore.js'
import { storeToRefs } from 'pinia'
const userStore = useUserStore()
// 解构 userStore.user
const { user } = storeToRefs(userStore)
// 修改 userStore 数据,观察浏览器的本地存储器 sessionStorage 和 cookie 是否同步修改
const chgUserData = () => {
userStore.$patch({
user: {
userId: 888,
username: 'Samdy_Chan',
age: 18,
addr: 'gz',
},
})
}
</script>
<style lang="scss" scoped>
</style>
6.1、测试持久化数据同步前
如下图,点击页面的【修改 userStore 数据】按钮前,页面及浏览器本地的 sessionStorage 和 cookie 存储器 userStore 都是为空对象:
6.2、测试持久化数据同步后
如下图,点击页面的【修改 userStore 数据】按钮后,页面及浏览器本地的 sessionStorage 和 cookie 存储器 userStore 都已经有数据了:
如下,cookie 存储器中的数据也同步有了,只不过是 cookie 数据默认是通过 urlencoded 编码的
(完)
觉得好的友友们,别忘了留个脚印和一键三连哦😊😊😊!!!