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.mzph.cn/bicheng/50025.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

实战机器学习--决策树分类器在蘑菇分类中的应用

数据集&#xff1a;https://pan.quark.cn/s/4d3526600c0c 在机器学习领域&#xff0c;图像分类是一个常见的任务&#xff0c;尤其是在自然语言处理和生物识别等领域。本文将通过一个简单的例子&#xff0c;展示如何使用Python和一些流行的库来实现蘑菇的分类&#xff0c;区分可…

docker 部署 LaTeX 环境

docker 部署 LaTeX 环境 需求表述部署步骤环境补丁&#xff08;解决 picins.sty 缺失问题&#xff09; 同步发布在个人笔记docker 部署 LaTeX 环境 需求表述 想做一个项目&#xff0c;需要一个 LaTeX 的中文环境&#xff0c;由于习惯了在服务器上用 docker 部署环境&#xff0…

pgsql的update语句在set里进行字段的运算 SET sort = sort +1

一、场景 需求&#xff1a;version 版本字段是记录数据更新的次数&#xff0c;新增时自动填充 version1 ,每更新一次数据 version就自增1。项目里单表插入和更新要手写update语句进行插入和更新。 –表中int4类型的字段 version 是1时&#xff0c;由1变成2 – version 是null…

【Linux】信号(signal)

目录 一、信号概念&#xff1a; 二、信号的常见状态&#xff1a; 信号递达&#xff1a; 信号未决&#xff1a; 阻塞信号&#xff1a; 忽略信号&#xff1a; 信号在内核中的表示&#xff1a; 三、信号相关函数&#xff1a; sigset_t &#xff08;类型&#xff09;&…

二、QGroundControl开发环境搭建

文章目录 环境列表QGC源码下载编译 环境列表 QGC GithubPX4-AutopilotQt 5.15Ubuntu20.04 QGC源码下载编译 官网下载指令 如下 // Clone the repo (or your fork) including submodules: git clone --recursive -j8 https://github.com/mavlink/qgroundcontrol.git // Upda…

Axure中继器实战篇:让数据展示和交互设计更上一层楼!

Axure中继器实战篇:让数据展示和交互设计更上一层楼! 前言 经过了前两章的学习,接下来我们去模拟的实际场景开启实战篇,以下是界面 1.前期准备 前期把页面准备好后,给中继器的每个单元格命名为了方便数据绑定的操作。 为了演示我准备了几十行数据,建议也多准备一点。…

后端返回一个图片链接,前端如何实现下载功能?

纯原创文章&#xff0c;转载请说明来源。 一、背景 要实现一个下载功能&#xff0c;后端直接返回了一个图片的地址https://xxxxx/pic.jpg。如果我们直接通过window.open(url, _blank) 的方式去下载这个图片&#xff0c;会发现 Chrome 浏览器会对这个图片进行预览&#xff0c;…

魅族手机怎么录屏?详细步骤助你轻松上手

“有人知道魅族手机怎么录屏吗&#xff0c;最近我在准备一些教学视频&#xff0c;急需用到手机的录屏功能来记录操作过程&#xff0c;但遗憾的是&#xff0c;我翻遍了设置也没能找到录屏的开关。所以&#xff0c;我在这里想问问大家&#xff0c;魅族手机是如何启动录屏功能的&a…

【PyTorch】图像多分类项目部署

【PyTorch】图像多分类项目 【PyTorch】图像多分类项目部署 如果需要在独立于训练脚本的新脚本中部署模型&#xff0c;这种情况模型和权重在内存中不存在&#xff0c;因此需要构造一个模型类的对象&#xff0c;然后将存储的权重加载到模型中。 加载模型参数&#xff0c;验证模型…

Sftp和ftp 区别、工作原理

Sftp的工作原理&#xff1a; SFTP的工作原理基于SSH协议&#xff0c;通过加密连接和安全认证来保障文件传输的安全性。 SFTP&#xff08;SSH File Transfer Protocol&#xff09;是一个确保数据在传输过程中安全的协议&#xff0c;它通过为传输的数据提供加密保护和对用户…

Docker重启策略和缩小镜像体积

目录 Docker重启策略 命令格式 命令选项 Docker缩小镜像体积 Docker重启策略 命令格式 docker run --restartno|always|on-failure|unless-stopped .... 命令选项 no&#xff1a;不管容器是正常退出还是异常退出&#xff0c;都不会重启容器。默认策略。always&#xf…

Java面试锦集 之 一、Java基础(1)

一、Java基础&#xff08;1&#xff09; 1.final 关键字的作用&#xff1f; 修饰变量&#xff1a; 一旦被赋值&#xff0c;就不能再被修改&#xff0c;保证了变量值的稳定性。 例&#xff1a; final int NUMBER 10; //之后就不能再改变 NUMBER 的值了。修饰方法&#xff1a;…

图解 HDFS 架构 |读写过程

HDFS HDFS 全称 Hadoop Distributed File System&#xff0c;是一个分布式文件系统。HDFS&#xff08;Hadoop Distributed File System&#xff09;是 Apache Hadoop 生态系统的一部分&#xff0c;它是一个分布式文件系统&#xff0c;用于存储和处理大规模数据集。HDFS 专门设…

【学习笔记】子集DP

背景 有一类问题和子集有关。 给你一个集合 S S S&#xff0c;令 T T T 为 S S S 的超集&#xff0c;也就是 S S S 所有子集的集合&#xff0c;求 T T T 中所有元素的和。 暴力1 先预处理子集的元素和 A i A_i Ai​&#xff0c;再枚举子集。 for(int s0; s<(1<…

源代码防泄密如何做?企业如何有效选择源代码防泄密产品?

源代码防泄密怎么选&#xff1f;如何高效做源代码防泄密工作&#xff1f; 源代码开发环境复杂&#xff0c;涉及的开发软件和文件类型众多且变化多端&#xff0c;那么究竟有哪些源代码防泄密软件能够适应各种开发软件而不影响原有的工作效率呢&#xff1f; 对于研发人员来说&a…

SpringBoot3 使用虚拟线程

目录 环境 说明 application.properties pom.xml Controller Java 验证 环境 Java Java: graalvm-jdk-21Springboot3.3.1 说明 springboot3.x 打开虚拟线程非常简单&#xff0c;只需添加一行配置信息即可。 spring.threads.virtual.enabled true application.properti…

探索 Framer Motion 高级动画技巧:提升前端设计水平

在现代的网页和应用设计中&#xff0c;动画不仅仅是视觉的点缀&#xff0c;更是用户体验的重要组成部分。它能够使界面更具吸引力&#xff0c;提升交互的流畅性&#xff0c;甚至在不经意间传达品牌的个性和态度。然而&#xff0c;要创造出令人惊叹的动效并不容易——直到有了 F…

经验——OLED的使用

型号&#xff1a;HS96L01W 4S03 分辨率&#xff1a;120*64 通讯方式&#xff1a;4线SPI 模式00 MCU&#xff1a;MSPM0G3507&#xff08;只影响SPI的配置&#xff09; 原本照着型号搜到了嘉立创的使用文档&#xff0c;但是实际上并不能正常使用&#xff0c;后来寻到了一篇博客…

PyTorch可以用来干嘛?

PyTorch 是一个广泛使用的开源机器学习库&#xff0c;由 Facebook AI Research&#xff08;FAIR&#xff09;开发。它主要用于计算机视觉和自然语言处理等深度学习领域&#xff0c;但也可以应用于许多其他类型的机器学习任务。PyTorch 提供了丰富的功能和灵活的设计&#xff0c…

MFC与QT中禁用Esc、Alt+F4、关闭图标

在业务中&#xff0c;我们需要按指定的方式才能关闭当前对话框。如下图需输入密码点击确认后&#xff0c;界面才能关闭。 方法1&#xff1a;通过禁用界面的按钮以及键盘上对应关闭对话框的按键。 1.灰度化关闭按钮 在对话框初始化部分添加将关闭按钮禁用 //MFC CMenu *pSysMe…