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

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.lryc.cn/news/394455.html

相关文章:

  • React Redux使用@reduxjs/toolkit的hooks
  • Rejetto HFS 服务器存在严重漏洞受到攻击
  • Electron开发 - 如何在主进程Main中让node-fetch使用系统代理
  • vue2 webpack使用optimization.splitChunks分包,实现按需引入,进行首屏加载优化
  • 深入理解 Docker 容器技术
  • redis并发、穿透、雪崩
  • 【架构设计】-- ACK 机制
  • 这些网络安全知识,请务必牢记!
  • 学习笔记——交通安全分析11
  • Python 3 编程第一步
  • 【eMTC】eMTC 窄带以及带宽的关系
  • 【MySQL】mysqldumpslow工具 -- 总结慢查询日志文件
  • 【mindspore进阶】02-ResNet50迁移学习
  • 智能决策的艺术:揭秘决策树的奇妙原理与实战应用
  • 基于AOP的数据字典实现:实现前端下拉框的可配置更新
  • 基于CentOS Stream 9平台搭建RabbitMQ3.13.4以及开机自启
  • 9、Redis 高级数据结构 HyperLogLog 和事务
  • MyBatis(30)如何在 MyBatis 中使用 XML 和注解混合配置方式
  • 强化学习与控制模型结合例子
  • RKNN3588——利用推理YOLOv8推理图片
  • 【ARMv8/v9 GIC 系列 1.7 -- GIC PPI | SPI | SGI | LPI 中断使能配置介绍】
  • uniapp开发射击类小游戏
  • spring6框架解析(by尚硅谷)
  • Open3D 计算点云的马氏距离
  • Java事务(Transaction)
  • 算法 —— 二分查找
  • Mysql explain语句详解与实例展示
  • Python基础问题汇总
  • 【讲解下iOS语言基础】
  • 【网络安全】实验一(网络拓扑环境的搭建)