当前位置: 首页 > news >正文

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

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 若依Vue前后端分离版如何部署(windows)(超详细)
  • Python爬虫(5) --爬取网页视频
  • MacOS安装SDKMan管理Java版本
  • libtins初探-抓包嗅探
  • 微信小程序canvas 使用案例(一)
  • android13读取cpu频率,并调整频率
  • 【环境搭建】使用openSfM+MVSNet重建稠密点云
  • 数据结构初阶-单链表
  • Mysql随记
  • 阿里云OSS对象存储的项目实战操作
  • uniapp中给data中的变量赋值报错
  • matlab仿真 模拟调制(下)
  • 总结——TI_音频信号分析仪
  • Golang | Leetcode Golang题解之第260题只出现一次的数字III
  • Llama 3.1要来啦?!测试性能战胜GPT-4o
  • [PHP内核探索]PHP中的哈希表
  • Bytom交易说明(账户管理模式)
  • CSS 专业技巧
  • CSS3 变换
  • ESLint简单操作
  • Github访问慢解决办法
  • httpie使用详解
  • JavaScript 一些 DOM 的知识点
  • JavaScript函数式编程(一)
  • javascript数组去重/查找/插入/删除
  • JAVA之继承和多态
  • js如何打印object对象
  • spring security oauth2 password授权模式
  • Vue官网教程学习过程中值得记录的一些事情
  • vue中实现单选
  • Vultr 教程目录
  • 大整数乘法-表格法
  • 第三十一到第三十三天:我是精明的小卖家(一)
  • 分类模型——Logistics Regression
  • 服务器从安装到部署全过程(二)
  • 海量大数据大屏分析展示一步到位:DataWorks数据服务+MaxCompute Lightning对接DataV最佳实践...
  • 每个JavaScript开发人员应阅读的书【1】 - JavaScript: The Good Parts
  • 前端每日实战:70# 视频演示如何用纯 CSS 创作一只徘徊的果冻怪兽
  • 前嗅ForeSpider采集配置界面介绍
  • 驱动程序原理
  • 如何利用MongoDB打造TOP榜小程序
  • 如何设计一个微型分布式架构?
  • 世界编程语言排行榜2008年06月(ActionScript 挺进20强)
  • 大数据全解:定义、价值及挑战
  • ​学习笔记——动态路由——IS-IS中间系统到中间系统(报文/TLV)​
  • #mysql 8.0 踩坑日记
  • (1)Android开发优化---------UI优化
  • (C语言版)链表(三)——实现双向链表创建、删除、插入、释放内存等简单操作...
  • (react踩过的坑)Antd Select(设置了labelInValue)在FormItem中initialValue的问题
  • (笔试题)分解质因式
  • (二十三)Flask之高频面试点
  • (回溯) LeetCode 78. 子集
  • (原)本想说脏话,奈何已放下
  • (转载)深入super,看Python如何解决钻石继承难题
  • *** 2003