vue前端通过sessionStorage缓存字典

正常来说,一个vue项目前端需要用到的一些翻译字典对象保存方式一般有多重,

  1. 新建js文件方式保存
  2. 通过vuex方式保存
  3. 通过sessionStorage保存
  4. 通过localStorage保存

正常以上几点的保存方式是够用了。
但是,当有字典不能以文件方式保存并且字典量很多很大时候,要考虑的事情就多了。
首选最新考虑存储的地方是vuex跟session,安全性会相对高一些,其次就需要考虑如果量大的问题。当字典数据量超过5MB的话,那session就有些难受了。而vuex持久存储也是需要先存Storage中再取回到内存中用。那么怎么比较好解决这个量大且不能以文件存储方式呢。

思路:
(字典都是从后端调接口获取)

  1. 还是通过session方式储存,额外有的看需求要不要再存储到vuex中
  2. 给session增加存储过期时间
  3. 给session增加存储量是否接近5MB存储上限判断
  4. 字典通过后端调接口获取
    4.1 获取地方 1.通过路由跳转时beforeRouteEnter回调中调用跟判断
    4.2 获取地方 2.通过页面created 回调中调用跟判断(有的是弹框子组件或者form表单并没有进行路由跳转)
  5. 由于基本每个菜单页面都要使用到字典,所以考虑通过混入mixin方式
  6. #由于字典一般用于选项跟翻译,所以需要考虑是否使用 async/await方式来同步代码,确保字典数据先取到再进入页面。是否使用各有利弊。

混入代码:

  1. window.g.SESSION_TIMEOUT 是定义全局变量,可配置
  2. DICE_KEYS 是存储字典key的数组
  3. SESSION_TIMEOUT 为字典过期时间
export default function (dictKeys = []) {let _isBeforeRouteEnterDictQuery = falsereturn {data() {return {m_dictsFin: false,m_dicts: {}}},provide: function () {return {m_dicts: this.m_dicts}},methods: {getSessionStorageSize(){let obj = ''let size = 0if(!window.sessionStorage){try {throw Error('浏览器不支持sessionStorage')} catch (error) {console.log(error)}}else {obj = window.sessionStorage}if(obj !== ''){for(item in obj){if(obj.hasOwnProperty(item)){size += obj.getItem(item).length}}}let val = (size/1024).toFixed(2) //单位KB 5MB = 1024*5 = 5120kB// 1024 * 4.5 = 4608if(val > 4608){ //如果存储大小超过4.5MB则需清空KEY重新获取过return true}else {return false}},//如果上面一个获取方法不可用,可以考虑使用这个方法替换estimateSessionStorageSize() {let totalSize = 0;// 遍历 sessionStorage 中的每个项for (let i = 0; i < sessionStorage.length; i++) {const key = sessionStorage.key(i)const value = sessionStorage.getItem(key)// 估算每个项的大小(这里简单估算每个字符占2个字节)// 注意:这只是一个非常粗略的估算const size = (new Blob([key + value])).size// 累加大小totalSize += size}let val = (totalSize/1024).toFixed(2) //单位KB 5MB = 1024*5 = 5120kB// 1024 * 4.5 = 4608if(val > 4608){ //如果存储大小超过4.5MB则需清空KEY重新获取过return true}else {return false}},setPageConfig(res,vm){const list = res?.data?.data || []store.dispatch('dynamicDicts', list)const pathAllDict = {}if (list && list.length > 0) {const sessionName = []list.forEach(e => {if (e) {if(vm){vm.$set(vm.m_dicts, e.dictCode, e.dictDatas)}else {this.$set(this.m_dicts, e.dictCode, e.dictDatas)}sessionName.push(e.dictCode)pathAllDict[e.dictCode] = e.dictDatassessionStorage.setItem(e.dictCode, JSON.stringify(e.dictDatas))}})store.commit('SET_DICT_DATA', pathAllDict)let currentSessionKey = sessionStorage.getItem('DICE_KEYS') ? sessionStorage.getItem('DICE_KEYS').split(',') : []console.log('setPageConfig',currentSessionKey,sessionName)console.log('DICE_KEYS',[...new Set([...currentSessionKey,...sessionName])])sessionStorage.setItem('DICE_KEYS', [...new Set([...currentSessionKey,...sessionName])])if(vm){vm.$nextTick(() => {vm.m_dictsFin = true})}else {this.m_dictsFin = true}}}},beforeRouteEnter(to, from, next) {_isBeforeRouteEnterDictQuery = truenext(async vm => {const date = new Date().getTime()let DICE_KEYS = sessionStorage.getItem('DICE_KEYS') || []if(!DICE_KEYS || DICE_KEYS.length === 0){ //没存字典或者已全删除//重新设置过期时间let timing = date + 1000 * 60 * window.g.SESSION_TIMEOUTsessionStorage.setItem('SESSION_TIMEOUT', timing)//调用接口if(dictKeys && dictKeys.length > 0){await queryBatchCode(dictKeys, { isNoLoading: true }).then(res => {vm.setPageConfig(res,vm)}).catch(e => {console.log('catch')next()})}}else {//获取过期时间let timeout = sessionStorage.getItem('SESSION_TIMEOUT')const preSessionS = DICE_KEYS.length>0 ? DICE_KEYS.split(',') : [] //转为数组if(vm.getSessionStorageSize()){preSessionS.forEach(item => {sessionStorage.removeItem(item)//清除所有字典})sessionStorage.setItem('DICE_KEYS',[])//重新设置过期时间let timing = date + 1000 * 60 * window.g.SESSION_TIMEOUTsessionStorage.setItem('SESSION_TIMEOUT', timing)//调用接口if(dictKeys && dictKeys.length > 0){await queryBatchCode(dictKeys, { isNoLoading: true }).then(res => {vm.setPageConfig(res,vm)}).catch(e => {console.log('catch')next()})}}else {if(timeout){if(timeout - date <= 0){ //已过期preSessionS.forEach(item => {sessionStorage.removeItem(item)//清除所有字典})sessionStorage.setItem('DICE_KEYS',[])//重新设置过期时间let timing = date + 1000 * 60 * window.g.SESSION_TIMEOUTsessionStorage.setItem('SESSION_TIMEOUT', timing)if(dictKeys && dictKeys.length > 0){await queryBatchCode(dictKeys, { isNoLoading: true }).then(res => {vm.setPageConfig(res,vm)}).catch(e => {console.log('catch')next()})}} else {//将已存在于session重的key,挂载到m_dicts对象重let sessionKeyList = dictKeys.filter(item => preSessionS.includes(item))sessionKeyList.forEach(e => {if (e) {vm.$set(vm.m_dicts, e, JSON.parse(sessionStorage.getItem(e)))}})//当前dictKeys匹配session中不存在的key去请求let reqKeyList = dictKeys.filter(item => !preSessionS.includes(item))if(reqKeyList.length >0){await queryBatchCode(reqKeyList, { isNoLoading: true }).then(res => {vm.setPageConfig(res,vm)}).catch(e => {console.log('catch')next()})}}}else {//重新设置过期时间let timing = date + 1000 * 60 * window.g.SESSION_TIMEOUTsessionStorage.setItem('SESSION_TIMEOUT', timing)//调用接口if(dictKeys && dictKeys.length > 0){await queryBatchCode(dictKeys, { isNoLoading: true }).then(res => {vm.setPageConfig(res,vm)}).catch(e => {console.log('catch')next()})}}}}})},// 有些非路由跳转触发的组件, 在 created 中调用async created() {if (_isBeforeRouteEnterDictQuery) returnif (!this.m_dictsFin) {const date = new Date().getTime()let DICE_KEYS = sessionStorage.getItem('DICE_KEYS') || []if(!DICE_KEYS || DICE_KEYS.length === 0){ //没存字典或者已全删除//重新设置过期时间let timing = date + 1000 * 60 * window.g.SESSION_TIMEOUTsessionStorage.setItem('SESSION_TIMEOUT', timing)//调用接口if(dictKeys && dictKeys.length > 0){await queryBatchCode(dictKeys, { isNoLoading: true }).then(res => {this.setPageConfig(res)})}}else {//获取过期时间let timeout = sessionStorage.getItem('SESSION_TIMEOUT')const preSessionS = DICE_KEYS.length>0 ? DICE_KEYS.split(',') : [] //转为数组if(this.getSessionStorageSize()){preSessionS.forEach(item => {sessionStorage.removeItem(item)//清除所有字典})sessionStorage.setItem('DICE_KEYS',[])//重新设置过期时间let timing = date + 1000 * 60 * window.g.SESSION_TIMEOUTsessionStorage.setItem('SESSION_TIMEOUT', timing)//调用接口if(dictKeys && dictKeys.length > 0){await queryBatchCode(dictKeys, { isNoLoading: true }).then(res => {this.setPageConfig(res)})}}else {if(timeout){if(timeout - date <= 0){ //已过期preSessionS.forEach(item => {sessionStorage.removeItem(item)//清除所有字典})sessionStorage.setItem('DICE_KEYS',[])//重新设置过期时间let timing = date + 1000 * 60 * window.g.SESSION_TIMEOUTsessionStorage.setItem('SESSION_TIMEOUT', timing)if(dictKeys && dictKeys.length > 0){await queryBatchCode(dictKeys, { isNoLoading: true }).then(res => {this.setPageConfig(res)})}} else {//将已存在于session重的key,挂载到m_dicts对象重let sessionKeyList = dictKeys.filter(item => preSessionS.includes(item))sessionKeyList.forEach(e => {if (e) {this.$set(this.m_dicts, e, JSON.parse(sessionStorage.getItem(e)))}})//当前dictKeys匹配session中不存在的key去请求let reqKeyList = dictKeys.filter(item => !preSessionS.includes(item))if(reqKeyList.length >0){await queryBatchCode(reqKeyList, { isNoLoading: true }).then(res => {this.setPageConfig(res)})}}}else {let timing = date + 1000 * 60 * window.g.SESSION_TIMEOUTsessionStorage.setItem('SESSION_TIMEOUT', timing)//调用接口if(dictKeys && dictKeys.length > 0){await queryBatchCode(dictKeys, { isNoLoading: true }).then(res => {this.setPageConfig(res)})}}}}}}}
}

在具体页面中使用

import pageDictMixin from '@/mixin/page-dict-mixin'mixins: [pageDictMixin(['DICT_YES_NO'])],

html部分代码

<el-optionv-for="item in m_dicts.DICT_YES_NO" :key="item.dataValue":label="item.dataLabel" :value="item.dataValue" />

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

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

相关文章

【SSL 1056】最大子矩阵 (多维DP)

题目大意 已知矩阵的大小定义为矩阵中所有元素的和。给定一个矩阵&#xff0c;你的任务是找到最大的非空&#xff08;大小至少是 1 ∗ 1 1*1 1∗1&#xff09;子矩阵。 比如&#xff0c;如下 4 ∗ 4 4*4 4∗4 子矩阵 0 -2 -7 0 9 2 -6 2 -4 1 -4 1 -1 8 0 -2 的最大子矩阵是 …

组件丰富、支持2/3D数据可视化的编辑器平台软件?

数据可视化编辑器通常用于创建交互式的图表和模型&#xff0c;可以帮助用户以更直观的方式展示数据。一些在线平台软件提供了丰富的组件&#xff0c;支持2D和3D数据可视化&#xff1a; 1、Plotly - 提供了多种语言的库&#xff0c;支持在线创建交互式图表&#xff0c;包括2D和…

Java 反射机制允许在运行时动态地访问和操作类的成员

Java 反射机制允许在运行时动态地访问和操作类的成员。 反射基本步骤 获取类的 Class 对象&#xff1a; Class<?> messageHandlerClass Class.forName("org.example.MsgHandler");Class.forName 方法根据类名获取相应的 Class 对象。 获取构造函数并创建实…

Qt 使用QJsonModel的问题

项目场景&#xff1a; 需要表格记录json数据&#xff0c;使用Qtreeview显示并修改&#xff0c;使用开源的第三方类QJsonModel,即可快速完成。 问题描述&#xff1a; 使用中发现一个问题&#xff1a;当Qtreeview修改完毕&#xff0c;从Model获取保存后的Json数据时&#xff0c…

mac|Mysql WorkBench导入文件失败(修改编码)

⚠️&#xff1a;表格中有中文的不适用表格中有中文的不适用表格中有中文的不适用表格中有中文的不适用 我有一个excel表&#xff0c;想导入到mysql数据库中&#xff0c;但是Workbench的导入格式只支持csv&#xff0c;通过excel、wps将excel另存为csv文件进行导入 导入会因为编…

【软件测试】之自动化测试

&#x1f3c0;&#x1f3c0;&#x1f3c0;来都来了&#xff0c;不妨点个关注&#xff01; &#x1f3a7;&#x1f3a7;&#x1f3a7;博客主页&#xff1a;欢迎各位大佬! 文章目录 什么是自动化测试Selenium介绍什么是SeleniumSelenium的特点工作原理 SeleniumJava环境搭建下载…

第1章 信息系统综合知识

第1章 信息系统综合知识 本章主要介绍信息系统综合知识&#xff0c;介绍信息、信息系统的基本概念&#xff0c;概述两化融合和国家信息化战略&#xff0c;讲解电子政务、电子商务的典型应用&#xff0c;描述信息化整体总体规划以及IT战略的主要内容。 1.1 信息的定义和属性 …

数据结构底层之HashMap(面经篇1)

1 . 讲一下hashmap的数据结构 HashMap是一种基于哈希表实现的数据结构&#xff0c;通常用于关联键值对&#xff0c;其中键是唯一的&#xff0c;而值可以重复。在Java中&#xff0c;HashMap是java.util.Map接口的一个实现&#xff0c;它提供了快速的查找、插入和删除操作。 数据…

【TB作品】矩阵键盘电话拨号,ATMEGA16单片机,Proteus仿真 atmega16矩阵键盘电话拨号

atmega16矩阵键盘电话拨号 c代码和仿真图&#xff1a; 使用ATmega16实现矩阵键盘电话拨号功能 项目背景 在电子设计和嵌入式系统开发中&#xff0c;矩阵键盘是常见的人机交互方式。它可以实现较多按键的输入&#xff0c;同时节省单片机的I/O资源。结合LCD显示和蜂鸣器&am…

Flume集群部署(手把手部署图文详细版)

前景概要&#xff1a; Kafka消息订阅系统在大数据业务中有着重要运用&#xff0c;尤其在实时业务中&#xff0c;kafka是必不可少的组件之一。 Flume是大数据组件中重要的数据采集工具&#xff0c;我们常利用Flume采集各种数据源的数据供其他组件分析使用。例如在实时业务中&…

清华镜像源

python在安装各种库的时候为了下载速度快&#xff0c;经常使用镜像源&#xff0c;下面是使用清华镜像源案例。其中的 xxx 表示要安装的库&#xff0c;如 requests。 pip install xxx -i https://pypi.tuna.tsinghua.edu.cn/simple 安装requests案例&#xff1a;pip install r…

Java房屋租赁管理系统附论文

作者介绍&#xff1a;计算机专业研究生&#xff0c;现企业打工人&#xff0c;从事Java全栈开发 主要内容&#xff1a;技术学习笔记、Java实战项目、项目问题解决记录、AI、简历模板、简历指导、技术交流、论文交流&#xff08;SCI论文两篇&#xff09; 上点关注下点赞 生活越过…

【Java09】方法(下)

1. 形参个数可变的方法 Java允许方法指定数量不确定的形参。如果在定义方法是&#xff0c;在最后一个形参的类型后加...&#xff0c;则表明该形参可以接受多个参数值。多个参数值作为数组传入&#xff1a; public class Varargs {public static void test(int a, String... b…

以智能化为舵手,引领现代计算机系统架构新航向

编者按&#xff1a;如今计算机系统承载的服务和算法逻辑日益复杂&#xff0c;理解、设计并改进计算机系统已成为核心挑战。面对系统复杂度和规模的指数级增长&#xff0c;以及新的大模型驱动场景下的分布式系统形态的涌现&#xff0c;人们亟需创新方法与技术来应对。在计算机系…

Linux 下c++ 的ssh服务端验证代码示例

telnet 是明文传输,别人可能用抓包软件就能截获通信内容,所以现代通信方式多用ssh。 在Linux下编写一个基本的SSH服务端验证代码示例,涉及到C++编程和使用OpenSSH库。以下是一个简单的示例,展示了如何建立一个基本的SSH服务端,并进行用户名和密码的验证。 环境准备 确保…

vue动态组件与插件到底是什么?

background: yellow; } 子组件1 <ul><li v-for"item of items" :key"item"><input type"checkbox" />{{ item }}</li></ul>子组件2 PostMail 子组件3 RecycleBin ![在这里插入图片描述](https://img-blog.csdni…

光明领鲜物流荣膺“2023中国冷链物流百强企业”荣誉称号

近日&#xff0c;以“全球链接跨界融合”为主题的2024第十六届全球食品冷链大会举行&#xff0c;光明乳业旗下光明领鲜物流受邀参加。 作为光明乳业全产业链中重要组成部分&#xff0c;光明领鲜物流始终保持高标准严要求&#xff0c;专注于冷链质量和服务持续完善&#xff0c;并…

【SQL】索引过多的缺点

索引并不是建得越多越好。虽然索引可以提高查询性能&#xff0c;但它们也带来了一些负面影响&#xff0c;特别是在数据修改操作&#xff08;插入、更新、删除&#xff09;和存储空间方面。以下是一些需要考虑的因素和权衡&#xff1a; 1. 写操作的性能影响 每个索引在数据修改…

1.英语中的从句学习

名词性从句&#xff1a; 1.最常见的连接词是that在宾语从句中的运用&#xff0c;如&#xff1a;I know that you will come. 句中的that 就是连接词&#xff0c;作用就是连接主句和从句&#xff0c;不充当成分也没有含义&#xff0c;只起风向标的作用&#xff0c;告诉你接下来…

Python基础语法(与C++对比)(持续更新ing)

代码块 Python在统一缩进体系内&#xff0c;为同一代码块C{...}内部的为同一代码块 注释 Python 单行注释&#xff1a;#... 多行注释&#xff1a;... C 单行注释&#xff1a;//... 多行注释: /*...*/ 数据类型 1. Python数据类型 Python中支持数字之间使用下划线 _ 分割…