网站首页 > 技术文章 正文
项目背景
项目采用的若依框架,但系统中会嵌入大屏、报表页面,是使用iframe来实现的。
若依框架的菜单管理中提供了缓存功能,是使用keep-alive实现的,但对于iframe页面并不生效,由于大屏页面加载本来就较慢,当用户切换tab页时,iframe要重载并且无法记录之前的操作内容,这非常影响用户体验。
keep-alive
keep-alive的缓存原理,其实是缓存的vnode,它的本质就是js对象,是一串数据,而对于iframe,缓存到的只有一个url,无法知悉其内部的结构与数据,因此无法进行缓存。
解决思路
绕开路由管理,在最外层文件(App.vue)中实现iframe动态加载,并搭配v-show控制iframe显示/隐藏。相当于通过定位,将一个独立的iframe页面覆盖在原有页面的最上方,
具体实现
- 配置菜单时,将含有iframe的页面多加一个配置参数 isIframe:true,用于前端区分
- store中存储:缓存的iframe信息{path,url}数组,菜单栏状态(根据菜单展开折叠状态来确定iframe的宽度)
const useIframesStore = defineStore(
'iframes',
{
state: () => ({
cacheIframes: [],
}),
actions: {
addIframe(iframe) {
this.cacheIframes.push(iframe)
},
delIframe(path) {
this.cacheIframes = this.cacheIframes.filter(item => item.path !== path)
},
clearCache() {
this.cacheIframes = []
}
}
}
)
- App.vue:v-for加载store中的已缓存的iframe信息,v-show的控制条件为比对当前路由的path于iframe的path是否一致。
- 样式问题:因为iframe组件不在router-view内,那么它和菜单是毫无关联的,需要独立设置其样式;为了正常显示效果,采用绝对定位的方式将它悬浮在正常页面的位置;width需要根据store中存储的菜单状态去显示对应的宽度
<template>
<router-view/>
<!-- iframe页 -->
<div v-if="route.path!=='/login'" :class="`iframes w-menu${sidebar.opened?'1':'0'}`" :style="`height:${iframeHeight};z-index:${route.query.isIframe?'999':'-999'}`">
<Iframe v-for="i in cacheIframes" :key="i.path" :src="i.url" v-show="route.path === i.path" title="iframe"></Iframe>
</div>
</template>
...
<style lang="scss" scoped>
.w-menu1{
width: calc(100% - #{$base-sidebar-width});
}
.w-menu0{
width: calc(100% - 54px);
}
</style>
- 路由守卫beforeEach:跳转路由时,根据路由参数isIframe为true时,表示即将跳转到iframe页面,调用store的方法往iframe数组中添加iframe信息
router.beforeEach((to, from, next) => {
const iframesStore = useIframesStore();
// 跳转iframe页
if(to.query.isIframe){
if(iframesStore.cacheIframes.filter(item => item.path === to.path).length==0){
// 添加缓存
iframesStore.addIframe({
path: to.path,
url: to.query.iframeUrl
})
}
}
next();
})
- 关闭tab签时:删除store中对应的iframe项
function closeSelectedTag(view) {
if(view.query.isIframe){
iframesStore.delIframe(view.path);
}
...
}
- 用户退出登录后,清空缓存
...
logOut() {
return new Promise((resolve, reject) => {
logout(this.token).then(() => {
this.token = ''
this.roles = []
this.permissions = []
removeToken()
// 清空缓存
useIframesStore().clearCache()
resolve()
}).catch(error => {
reject(error)
})
})
}
- 在若依菜单管理中将iframe页面,使用参数isIframe控制,而对应的组件页面设置为一个空白页,以避免同时加载两个iframe占用资源。
- 上一篇: IFRAME的各种经验总结
- 下一篇: Vue开发中使用iframe
猜你喜欢
- 2025-01-09 如何实现高性能的在线 PDF 预览
- 2025-01-09 再不用怕Markdown中的绘图,GitHub官方支持Mermaid图表绘制工具
- 2025-01-09 单点登录是什么?三种情况的实现方式
- 2025-01-09 Javascript一些实用技巧
- 2025-01-09 面试官问道:常见的跨域处理方式有哪些?
- 2025-01-09 跨域问题?同源策略大全
- 2025-01-09 Vue开发中使用iframe
- 2025-01-09 IFRAME的各种经验总结
- 2025-01-09 推荐!Iframe 的4种加载技术和性能优化!
- 2025-01-09 页面加载多个Iframe,白屏时间太长,如何优化?
- 02-21走进git时代, 你该怎么玩?_gits
- 02-21GitHub是什么?它可不仅仅是云中的Git版本控制器
- 02-21Git常用操作总结_git基本用法
- 02-21为什么互联网巨头使用Git而放弃SVN?(含核心命令与原理)
- 02-21Git 高级用法,喜欢就拿去用_git基本用法
- 02-21Git常用命令和Git团队使用规范指南
- 02-21总结几个常用的Git命令的使用方法
- 02-21Git工作原理和常用指令_git原理详解
- 最近发表
- 标签列表
-
- cmd/c (57)
- c++中::是什么意思 (57)
- sqlset (59)
- ps可以打开pdf格式吗 (58)
- phprequire_once (61)
- localstorage.removeitem (74)
- routermode (59)
- vector线程安全吗 (70)
- & (66)
- java (73)
- org.redisson (64)
- log.warn (60)
- cannotinstantiatethetype (62)
- js数组插入 (83)
- resttemplateokhttp (59)
- gormwherein (64)
- linux删除一个文件夹 (65)
- mac安装java (72)
- reader.onload (61)
- outofmemoryerror是什么意思 (64)
- flask文件上传 (63)
- eacces (67)
- 查看mysql是否启动 (70)
- java是值传递还是引用传递 (58)
- 无效的列索引 (74)