Vuex数据持久化实现

news2024/11/14 15:44:48

版本: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() 静态方法将一个或者多个源对象中所有可枚举的自有属性复制到目标对象,并返回修改后的目标对象。
        // 如果有相同的属性名后者会覆盖前者,这里把两个数据源的数据合并到 oldState
        Object.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 }

          // 将需要的模块存到 localStorage
          if(modulesKeys.local.length > 0){
            const localData = setData(store.state, modulesKeys.local)
            localStorage.setItem(key, JSON.stringify(localData))
          }else {
            localStorage.removeItem(key)
          }
          // 缓存到 session
          if(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.coloradmin.cn/o/1945158.html

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

相关文章

Java——————接口(interface) <详解>

1.1 接口的概念 在现实生活中&#xff0c;接口的例子比比皆是&#xff0c;比如&#xff1a;笔记本电脑上的USB接口&#xff0c;电源插座等。 电脑的USB口上&#xff0c;可以插&#xff1a;U盘、鼠标、键盘...所有符合USB协议的设备 电源插座插孔上&#xff0c;可以插&#xff…

小程序收银视频介绍

千呼新零售2.0系统是零售行业连锁店一体化收银系统&#xff0c;包括线下收银线上商城连锁店管理ERP管理商品管理供应商管理会员营销等功能为一体&#xff0c;线上线下数据全部打通。 适用于商超、便利店、水果、生鲜、母婴、服装、零食、百货、宠物等连锁店使用。 详细介绍请…

NC65 还款单的冲借款还款金额和报销单中冲借款的还款金额的计算逻辑

被报销单的冲借款界面中还款单金额计算逻辑&#xff0c;困扰了两天&#xff0c;无意中操作了&#xff0c;才搞清楚计算的逻辑&#xff08;感觉有点反人类&#xff09;。明明可以借款金额减去冲借款金额等于还款金额就行了&#xff0c;非得冲借款金额减去报销金额等于还款金额。…

数学基础【俗说矩阵】:逆矩阵

逆矩阵知识 认识逆矩阵 当最矩阵A【左乘】【初等阵】多次&#xff08;也就是进行多次【初等行】变化&#xff09;后&#xff0c;得到了一个【单位阵E】。由于矩阵具有结合律&#xff0c;把矩阵A【左乘】的所有【初等阵】乘起来&#xff0c;就得到了一个新的矩阵。我们称这个能…

Jenkins - apt 安装软件包 404 Not Found

Jenkins - apt 安装软件包 404 Not Found 引言关于 apt解决 apt 安装软件包 404 问题问题分析解决方案 引言 日常 Jenkins job 运行&#xff0c;有段时间会遇到 apt 安装软件包 404 的情况&#xff0c;这种情况不是每次都发生的&#xff0c;但是会导致 Jenkins 失败&#xff0…

强化学习术语与超参数整理(PPO)

最近在isaac lab中使用各个强化学习框架做对比训练&#xff0c;算法都是用的PPO&#xff0c;但是每个框架里超参数名字都不太一样&#xff0c;各种叫法弄得都混乱了&#xff0c;而且对齐不好很难对比出结论&#xff0c;在这里系统整理一下。 Isaac Lab支持的强化学习框架介绍-…

UE4-光照重建

当我们拉入新的光源和模型到我们的场景中后&#xff0c;会产生这样的情况&#xff1a; Preview:预览 表示此时由于光照物体所产生的阴影都是预览级别的并不是真正的效果。 方法一&#xff1a; 或者也可以在世界大纲中选中我们的光源&#xff0c;然后将我们的光源改变为可以…

免费【2024】springboot 毕业生就业管理微信小程序

博主介绍&#xff1a;✌CSDN新星计划导师、Java领域优质创作者、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和学生毕业项目实战,高校老师/讲师/同行前辈交流✌ 技术范围&#xff1a;SpringBoot、Vue、SSM、HTML、Jsp、PHP、Nodejs、Python、爬虫、数据可视化…

MPI框架以及PIPE数据流向细节

一、海思MPP内部处理流程图 各模块功能介绍&#xff1a; &#xff08;1&#xff09;VI:捕获视频图像&#xff0c;可对其做剪切、缩放、镜像等处理&#xff0c;并输出多路不同分辨率的图像数据. &#xff08;2&#xff09;AI:捕获⾳频数据&#xff0c;然后AENC 模块⽀持按多种⾳…

2024:Qt--编译配置Protobuf(windows10) 配图详解

这里写自定义目录标题 一、准备1、Window10系统2、Qt Creator 5.0.2 Based on Qt 5.15.2 (MSVC 2019, 64 bit)3、protobuf-3.15.0&#xff08;本示例使用版本&#xff09;4、cmake-3.21.3-windows-x86_64&#xff08;本示例使用&#xff0c;下载的zip直接解压使用&#xff09; …

代码随想录——零钱兑换Ⅱ(Leetcode518)

题目链接 完全背包 class Solution {public int change(int amount, int[] coins) {int[] dp new int[amount 1];dp[0] 1;for(int i 0; i < coins.length; i){for(int j coins[i]; j < amount; j){dp[j] dp[j - coins[i]];}}return dp[amount];} }本题为组合问题…

MySQL 约束 (constraint)

文章目录 约束&#xff08;constraint)列级约束和表级约束给约束起名字&#xff08;constraint)非空约束&#xff08;no null)检查约束&#xff08;check)唯一性约束 (unique)主键约束 (primary key)主键分类单一主键复合主键主键自增 &#xff08;auto_increment) 外键约束外什…

【IEEE出版 | 广东省高校联合主办】第六届物联网、自动化和人工智能国际学术会议(IoTAAI 2024,7月26-28)

第六届物联网、自动化和人工智能国际会议&#xff08;IoTAAI 2024&#xff09;将于2024年07月26-28日在中国广州召开。 会议旨在拓展国际科技学术交流渠道&#xff0c;搭建学术资源共享平台&#xff0c;促进全球范围内的科技创新&#xff0c;提升中外学术合作。会议还鼓励不同领…

BGP选路之Preferred value

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

FliFlik KleanOut for Photo 的妙用

FliFlik KleanOut for Photo 是一款专业的图像水印去除软件&#xff0c;旨在帮助用户快速高效地去除照片中的水印标识。无论是文本水印还是图像水印&#xff0c;该软件都能有效识别并删除&#xff0c;保持图像原始清晰度和质量。它采用 AI 算法引擎&#xff0c;可以精准识别和删…

MongoDB教程(十六):MongoDB高级索引

&#x1f49d;&#x1f49d;&#x1f49d;首先&#xff0c;欢迎各位来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里不仅可以有所收获&#xff0c;同时也能感受到一份轻松欢乐的氛围&#xff0c;祝你生活愉快&#xff01; 文章目录 引言一、全文索…

最简单的typora+gitee+picgo配置图床

typoragiteepicgo图床 你是否因为管理图片而感到头大&#xff1f;是时候了解一下 Typora、Gitee 和 PicGo 这个超级三剑客了&#xff0c;它们可以帮你轻松打造自己的图床&#xff0c;让你的博客图片管理变得简单又有趣。让我们开始这场神奇的图床之旅吧&#xff01; Typora …

大型语言模型的生物医学知识图优化提示生成

大型语言模型的生物医学知识图优化提示生成 https://arxiv.org/abs/2311.17330 https://github.com/BaranziniLab/KG_RAG 大型语言模型的生物医学知识图优化提示生成 摘要 KG-RAG框架&#xff0c;较好的结合了生物医学知识图谱SPOKE和LLM的优势。SPOKE是一个开放知识图谱&…

聚焦保险行业客户经营现状,概述神策数据 CJO 解决方案

触点红利时代&#xff0c;企业的经营需求从「深度的用户行为分析」转变为「个性化、全渠道一致的客户体验」。客户旅程编排&#xff08;Customer Journey Orchestration&#xff0c;简称 CJO&#xff09;从体验出发&#xff0c;关注客户需求、感受和满意度&#xff0c;能够帮助…

04 HTML CSS JavaScript

文章目录 HTML1、HTML介绍2、快速入门3、基础标签4、图片、音频、视频标签5、超链接标签6、列表标签7、表格标签8、布局标签9、 表单标签 CSS1、 概述2、 css 导入方式3、 css 选择器4、 css 属性 JavaScript1、JavaScript简介2、JavaScript引入方式3、JavaScript基础语法4、Ja…