状态管理是构建复杂应用的关键部分,Vuex 和 Pinia 作为 Vue 状态管理的两大工具,提供了强大的机制来维护和管理应用的状态。
所谓的状态持久化,指的是我们创建的状态需要跨越页面的生命周期,不随着页面的关闭或刷新而清理,然而,这些状态都是存储在内存里面的,即当浏览器关闭或刷新时,状态会丢失。 为了解决这个问题,状态持久化成为了一个必要的需求。
状态的持久化存储本身不是一件复杂的业务,可以通过多种方式实现,最终都是围绕存储在localStorage、sessionStorage 或 IndexedDB当中。
基本实现
基本方式就是直接根据需求编写代码:
- 存储:在变更状态的同时将状态存储到本地
- 读取:当页面重新打开或刷新时,先从本地获取原来仓库里面的状态
这种方式可以实现状态持久化,应该也是大多数人平时实现该业务所采取的方式,不过会有一些问题:
webStorage的存储是一件耗时行为,每次更新状态都进行本地存储会有效率问题- 如果是以不同
键存储在本地,数据过多时读写操作繁琐 - 存储行为与业务代码耦合
更优雅的方式
借助上面的思想,使用状态存储库的插件功能实现。
Pinia插件功能
Pinia的插件是一个函数,使用时调用use方法使用插件即可:
import { createPinia } from "pinia";
import registerPlugin from "./plugins/registerPlugin";
const pinia = createPinia();
pinia.use(registerPlugin);// 使用插件
编码插件实现状态持久化
// registerPlugin.js
const KEY_PREFIX = "PINIA:STATE:";
export default function (context) {
const { store } = context;
//注册页面卸载和刷新行为事件
window.addEventListener("beforeunload", function () {
localStorage.setItem(KEY_PREFIX + store.$id, JSON.stringify(store.$state));
});
// 读取数据
try {
const state = JSON.parse(localStorage.getItem(KEY_PREFIX + store.$id));
if (state) {
// 更新状态
store.$patch(state);
}
} catch (error) {
console.log("数据有误,无法存储");
}
}
Pinia插件函数接受一个参数,该参数是一个上下文对象context,包含
context.pinia // 用 `createPinia()` 创建的 pinia。
context.app // 用 `createApp()` 创建的当前应用(仅 Vue 3)。
context.store // 该插件想扩展的 store
context.options // 定义传给 `defineStore()` 的 store 的可选对象。
这里我们使用store仓库即可,插件函数会在注册仓库时执行,注册了几个仓库,插件函数就会执行几次,里面的仓库信息store是不同的仓库,这里一个是settings仓库,一个是permissions仓库,会打印两次,存储时候需要分开存储。
监听页面卸载和刷新事件,执行本地存储操作。
Vuex插件功能
Vuex插件也是一个函数,接受一个store仓库对象,函数在仓库创建的时候会执行。
import { createStore } from "vuex";
import registerPlugin from "./plugins/registerPlugin";
export default createStore({
state() {
return {
name: "",
};
},
mutations: {
setName(state, payload) {
state.name = payload;
},
},
// 注册插件
plugins: [registerPlugin],
});
实现状态持久化
// registerPlugin.js
const KEY = "VUEX:STATE";
export default function (store) {
window.addEventListener("beforeunload", function () {
localStorage.setItem(KEY, JSON.stringify(store.state));
});
try {
const state = JSON.parse(localStorage.getItem(KEY));
if (state) {
//替换
store.replaceState(state);
}
} catch (error) {
console.log("数据有误,无法存储");
}
}
持久化插件
Pinia和Vuex都现有持久化的插件供使用,分别是
-
pinia-plugin-persistedstate:github.com/prazdevs/pi… -
vuex-persist:github.com/championswi…
写在最后
Pinia 与 Vuex 的状态持久化是一项常见的业务,使用插件功能可以灵活地定制状态的持久化行为,以满足具体需求。状态库的插件功能是一种扩展机制,允许你在 store 创建之后执行额外的逻辑,虽说市面上有很多现成的插件,但是学会插件的使用也是必不可少的过程。
感谢您的阅读!