Vuex数据持久化实现

版本:vue 3.4.29 vuex4.1.0

1. 出现的问题

当我使用 vuex 作为状态管理组件来存储用户的一些信息之后,发现从/login 页面跳转到/home 界面后拿不到vuex信息。
之后查阅资料了解,当切换路由后,vue 会重新渲染,而vuex 也会重新初始化,之前的状态就会全部丢失。因此需要对vuex 中的数据进行持久化。
以下展示了两种持久化方案:

2. 基于window监听的持久化方案

由于页面刷新后会导致vuex 重新初始化,因此可以通过监听页面刷新事件来持久化数据。对应的事件就是beforeunload。之后再在初始化的时候恢复数据即可。

App.vuescript 标签中编译一下代码即可实现:

<script setup>
import {useStore} from 'vuex'
const store = useStore()
// 恢复
if(localStorage.getItem("store")){store.replaceState(Object.assign({}, store.state, JSON.parse(localStorage.getItem("store"))))
}
// 存储window.addEventListener("beforeunload", () => {localStorage.setItem("store", JSON.stringify(store.state))})
</script>

3. 基于Vuex 插件的持久化方案

Vuex 官方提供了plugins 插件的选项,这个选项暴露出每次mutation 的钩子,可以让用户在每次 store 初始化和每次mutation 之后插入一些功能代码。因此可以作为持久化的实现方式。

Vuex 插件就是一个函数,它接受store 作为唯一参数

const myPlugin = (store) => {// 当 store 初始化后调用store.subscribe((mutation, state) => {// 每次 mutation 之后调用// mutation 的格式为 { type, payload }})
}

然后像下面一样使用:

const store = createStore({// ...plugins: [myPlugin]
})

持久化实现:
本项目中采用模块化的方式使用vuexstate 根据功能拆分,如涉及用户的状态数据放在user.js 里,统一放在modules 文件夹下。
在这里插入图片描述

index.js 文件:
首先使用import.meta.glob 读取modules文件下的所有文件,并将个模块放入到modules 对象中

// 一次性加载 modules 文件夹下的所有 store 文件
const files = import.meta.glob('./modules/*.js', {eager: true})
let modules = {}// 遍历 files 对象, path为每个文件的路径
// Object.keys(object) 返回一个有对象属性名组成的数组
Object.keys(files).forEach((path) => {// 将 actions 、getters 等对象取出来const module = files[path].default// 将文件名取出来const modulesName = path.replace(/^\.\/(.*)\/(.*)\.\w+$/, '$2')modules[modulesName] = module
})

然后将modules 传入到自定义的插件中:

/*** 持久化 vuex 数据插件* 参数解释:*  key: 存储数据的键*  modules: 存储的具体数据模块*  modulesKeys: 存储数据的模块名数组*      这里分了两个区域:*          local 中的模块数据存在 localStorage 中*          session中的模块数据存在 session 中,这里为空,*          如果想存到这里可以自行设置*  建议用户相关的数据都存到 localStorage 里,因为 session 只针对当前会话,*  打开新的窗口就访问不到了*/
const persistent = Presistent({key: 'vuex', modules, modulesKeys:{local: Object.keys(modules),session: []
}})

其中Presistent 就是自定义的插件工具,返回一个Vuex的插件函数给persistent 变量,之后就能使用了。

presistent.js 文件:
插件函数的具体实现如下:

export default function Presistent({key, modules, modulesKeys}){// 返回 vuex 的插件函数return (store) => {// 当 store 初始化后调用// 拿到存在 local 和 session 里的旧的数据const localOldState = JSON.parse(localStorage.getItem(key) || '{}')const sessionOldState = JSON.parse(sessionStorage.getItem(key) || '{}')let oldState = {}// Object.assign() 静态方法将一个或者多个源对象中所有可枚举的自有属性复制到目标对象,并返回修改后的目标对象。// 如果有相同的属性名后者会覆盖前者,这里把两个数据源的数据合并到 oldStateObject.assign(oldState, localOldState, sessionOldState)// 每次重启vuex 都将历史数据从缓存中恢复状态if(Object.keys(oldState).length > 0){for(const oldKey in oldState){modules[oldKey] = oldState[oldKey]}store.replaceState(modules)}store.subscribe((mutation, state) => {// 每次 mutation 之后调用// mutation 的格式为 { type, payload }// 将需要的模块存到 localStorageif(modulesKeys.local.length > 0){const localData = setData(store.state, modulesKeys.local)localStorage.setItem(key, JSON.stringify(localData))}else {localStorage.removeItem(key)}// 缓存到 sessionif(modulesKeys.session.length > 0){const sessionData = setData(store.state, modulesKeys.session)sessionStorage.setItem(key, JSON.stringify(sessionData))}else {sessionStorage.removeItem(key)}})}
}function setData(state, module){let data = {}for(const i of module){data[i] = state[i]}return data
}

index.js 文件中的全部代码:

import { createStore } from 'vuex'
import Presistent from './presistent'// 一次性加载 modules 文件夹下的所有 store 文件
const files = import.meta.glob('./modules/*.js', {eager: true})
let modules = {}// 遍历 files 对象, path为每个文件的路径
// Object.keys(object) 返回一个有对象属性名组成的数组
Object.keys(files).forEach((path) => {// 将 actions 、getters 等对象取出来const module = files[path].default// 将文件名取出来const modulesName = path.replace(/^\.\/(.*)\/(.*)\.\w+$/, '$2')modules[modulesName] = module
})
console.log('moudles: ', modules)
const persistent = Presistent({key: 'vuex', modules, modulesKeys:{local: Object.keys(modules),session: []
}})export default createStore({modules: {...modules},plugins: [persistent]
})

参考资料:
插件实现代码来源:https://github.com/cmdparkour/vue-admin-box/tree/template-js
vuex插件介绍:https://vuex.vuejs.org/zh/guide/plugins.html
vite Glob 环境变量:https://cn.vitejs.dev/guide/features#glob-import

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.xdnf.cn/news/1486751.html

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

为什么样本方差(sample variance)的分母是 n-1?

样本均值与样本方差的定义 首先来看一下均值&#xff0c;方差&#xff0c;样本均值与样本方差的定义 总体均值的定义&#xff1a; μ 1 n ∑ i 1 n X i \mu\frac{1}{n}\sum_{i1}^{n} X_i μn1​i1∑n​Xi​ 也就是将总体中所有的样本值加总除以个数&#xff0c;也可以叫做总…

运维团队如何借助分布式部署提升监控效率与可靠性

随着企业IT基础设施的日益复杂和分布式架构的广泛应用&#xff0c;传统的监控解决方案已经难以满足现代运维团队的需求。在这样的背景下&#xff0c;分布式部署作为一种新型的监控架构&#xff0c;以其灵活性、可扩展性和高可用性&#xff0c;成为了运维团队提升监控效率与可靠…

centos系统mysql数据库差异备份与恢复

文章目录 差异备份mysql数据一、 安装 Percona XtraBackup数据库中创建一些数据三、创建全备份四、创建差异备份1. 在数据库中添加数据&#xff0c;让数据发生一些改变2. 创建第一个差异备份3. 数据库中再次添加一些数据4. 创建第二个差异备份 五、模拟数据丢失&#xff0c;删库…

nest学习笔记(一)

介绍 nest是一个用于构建高效&#xff0c;可拓展的nodejs服务端应用程序的框架&#xff0c;它使用渐进式javascript&#xff0c;使用Typescript构建并且完全支持Typescript&#xff0c;而且运行开发者使用javascript编写代码&#xff0c;提供了OOP、FP、FRP nest的底层是基于…

Kolla-Ansible的确是不支持CentOS-Stream系列产品了

看着OpenStack最新的 C 版本出来一段时间了&#xff0c;想尝个鲜、用Kolla-Ansible进行容器化部署&#xff0c;结果嘛。。。 根据实验结果&#xff0c;自OpenStack Bobcat版本开始&#xff0c;Kolla-Ansible就适合在CentOS系列产品上部署了&#xff0c;通过对 Bobcat和Caracal…

springcloud接入skywalking作为应用监控

下载安装包 需要下载SkyWalking APM 和 Java Agent 链接: skywalking 安装 下载JDK17&#xff08;可不配置环境变量&#xff09; 目前skywalking 9.0及以上版本基本都不支持JDK8&#xff0c;需要JDK11-21&#xff0c;具体版本要求在官网查看。 我这里使用的是skywalking9.…

每日好题(2)

#define _CRT_SECURE_NO_WARNINGS #include <stdio.h> int main(void) {int arr[6] { 1,2,3,4,5,6 };char* p arr;int sz sizeof(arr) / sizeof(arr[0]);for (int a 0; a < sz; a){printf("%d\n", *p);p 4;}return 0; }这串代码遍历打印数组的结果是没…

BGP选路之Preferred value

原理概述 当一台BGP路由器中存在多条去往同一目标网络的BGP路由时&#xff0c;BGP协议会对这些BGP路由的属性进行比较&#xff0c;以确定去往该目标网络的最优BGP路由&#xff0c;然后将该最优BGP路由与去往同一目标网络的其他协议路由进行比较&#xff0c;从而决定是否将该最优…

小程序多排数据横向滚动实现

如何实现多排数据滚动效果 swiper 外部容器 swiper-item 每一页的数据 因为现在有多排数据,现在在swiper-item 中需要循环一个数组 初版 <template><view><view class"container"><view class"swiper-box"><swiper class&qu…

操作系统——笔记(1)

操作系统是管理计算机硬件资源&#xff0c;控制其他程序运行并为用户提供交互操作界面的系统软件的集合&#xff0c;控制和管理着整个计算机系统的硬件和软件资源&#xff0c;是最基本的系统软件。 常见的操作系统&#xff1a;ios、windows、Linux。 计算机系统的结构层次&am…

“论软件测试中缺陷管理及其应用”写作框架,软考高级论文,系统架构设计师论文

原创范文 软件缺陷指的是计算机软件或程序中存在的某种破坏正常运行能力的问题、错误&#xff0c;或者隐藏的功能缺陷。缺陷的存在会导致软件产品在某种程度上不能满足用户的需要。在目前的软件开发过程中&#xff0c;缺陷是不可避免的。软件测试是发现缺陷的主要手段&#xf…

计算机网络基础:2.TCP/IP模型中的各层协议、IP地址

一、TCP/IP模型中的各层协议 接着第一篇餐厅运营的例子来解释一下TCP/IP五层模型中的每一层协议&#xff1a; 1. 应用层&#xff08;餐饮一体机&#xff09; 在TCP/IP模型中&#xff0c;应用层直接与用户交互&#xff0c;提供网络服务。这一层将OSI模型的应用层&#xff08;点…

colab进行keras入门随机数和标签的一点思考,例如shape和Dense等

keras官方中文文档 pip install kerasfrom keras import layers from keras import modelsmodel.add(layers.Dense(32,activationrelu,input_shape(100,)))# 添加多个Dense层 model.add(layers.Dense(10,activationsoftmax)) model.compile(optimizerrmsprop,losscategorical_…

pikachu之sql lnjet 字符型注入

先测试一下闭合 注释符号&#xff1a;-- 注释符号可以忽略其后的内容&#xff0c;使得后续的原始查询内容不会影响我们注入的SQL代码。 条件测试&#xff1a;通过and 11和and 12分别测试真假条件&#xff0c;可以判断输入是否成功闭合&#xff0c;并且可以检测注入是否成功。 …

Kotlin 协程 — 基础

Kotlin 协程 — 基础 协程已经存在一段时间了&#xff0c;关于它的各种文章也很多。但我发现想要了解它还比较费时&#xff0c;所以我花了一段时间才真正理解了协程的基础知识以及它的工作原理。因此&#xff0c;我想分享一些我理解到的内容。 什么是协程&#xff1f; 协程代表…

关于OLED的I2C手册记录

首先我们从淘宝上面找到对应OLED 4pin iic驱动的ssd1306手册&#xff0c;它有多种的驱动方式&#xff0c;我们只需要看看他这个i2c模式。 我们可以从中看到 Slave address R/W后面的#代表低电平是W。 SA0是它的一个 slave address bit 可以使用 这两个都可以作为OLED的 设备…

分布式事务与Seata落地

分布式事务与Seata落地 一、事务基础 1.1 本地事务 事务指的就是一个操作单元, 在这个操作单元中的所有操作最终要保持一致的行为, 要么所有操作都成功, 要么所有的操作都被撤销。 1.2 本地事务特性 本地事务四大特性: ACID A: 原子性(Atomicity), 一个事务中的所有操作, …

如何通过一条SQL变更多个分库分表?

数据库发展到今天&#xff0c;分库分表已经不是什么新鲜话题了&#xff0c;传统的单节点数据库架构在数据量和访问频次达到一定规模时&#xff0c;会出现性能瓶颈和扩展性问题&#xff0c;而分库分表技术通过将数据分散到多个数据库实例中来分担负载&#xff0c;从而提升系统的…

数字信号||离散序列的基本运算(2)

实验二 离散序列的基本运算 一、实验目的 (1)进一步了解离散时间序列时域的基本运算。 (2)了解MATLAB语言进行离散序列运算的常用函数&#xff0c;掌握离散序列运算程序的编写方法。 二、实验涉及的MATLAB子函数 1.find 功能&#xff1a;寻找非零元素的索引号。 调用格…

BGP选路之Local Preference

原理概述 当一台BGP路由器中存在多条去往同一目标网络的BGP路由时&#xff0c;BGP协议会对这些BGP路由的属性进行比较&#xff0c;以确定去往该目标网络的最优BGP路由。BGP首先比较的是路由信息的首选值&#xff08;PrefVal)&#xff0c;如果 PrefVal相同&#xff0c;就会比较本…