Vue无法对iframe进行缓存的解决方案
项目背景
项目采用的若依框架,但系统中会嵌入大屏、报表页面,是使用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占用资源。
到此这篇关于Vue无法对iframe进行缓存的解决方案的文章就介绍到这了,更多相关Vue iframe无法缓存内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!
最新评论