状态持久化:Pinia 与 Vuex 的持久化存储策略

949 阅读3分钟

状态管理是构建复杂应用的关键部分,VuexPinia 作为 Vue 状态管理的两大工具,提供了强大的机制来维护和管理应用的状态。

所谓的状态持久化,指的是我们创建的状态需要跨越页面的生命周期,不随着页面的关闭或刷新而清理,然而,这些状态都是存储在内存里面的,即当浏览器关闭或刷新时,状态会丢失。 为了解决这个问题,状态持久化成为了一个必要的需求。

状态的持久化存储本身不是一件复杂的业务,可以通过多种方式实现,最终都是围绕存储在localStoragesessionStorageIndexedDB当中。

基本实现

基本方式就是直接根据需求编写代码:

  • 存储:在变更状态的同时将状态存储到本地
  • 读取:当页面重新打开或刷新时,先从本地获取原来仓库里面的状态

这种方式可以实现状态持久化,应该也是大多数人平时实现该业务所采取的方式,不过会有一些问题:

  • 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仓库,会打印两次,存储时候需要分开存储。

1.png

监听页面卸载和刷新事件,执行本地存储操作。

2.png

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("数据有误,无法存储");
  }
}

持久化插件

PiniaVuex都现有持久化的插件供使用,分别是

写在最后

PiniaVuex 的状态持久化是一项常见的业务,使用插件功能可以灵活地定制状态的持久化行为,以满足具体需求。状态库的插件功能是一种扩展机制,允许你在 store 创建之后执行额外的逻辑,虽说市面上有很多现成的插件,但是学会插件的使用也是必不可少的过程。

感谢您的阅读!

22.gif