参考
# vue中使用keep- alive缓存机制,切换标签含有iframe标签的界面会被重新刷新的问题处理
序言
最近工作中,项目上遇到一个这样的需求,在某个功能页面根据菜单来来显示不同的业务组件,一般来说使用keep-alive都没啥问题。
<keep-alive>
<component
:is="curComponents"
/>
</keep-alive>
但是有个业务组件里面加载了第三方编辑器,而加载的方式是iframe(我们无法更改),发现在切换菜单时,带iframe的组件里面的第三方编辑器变成空白(iframe里面的body变成空),iframe中keep-alive机制失效原因:iframe页里的内容并不属于节点的信息,所以使用keep-alive依然会重新渲染iframe内的内容。而且iframe每一次渲染就相当于打开一个新的网页窗口,即使把节点保存下来,在渲染时iframe页还是刷新的。
解决方案
- 网上的方案是使用路由的解决方案:切换不含iframe的界面时使用vue路由,在切换含iframe页的界面时利用v-show来控制显示隐藏,使iframe的节点不被删除,以此来防止界面节点被重新更新,从而达到保存iframe节点数据的效果
- 我考虑了另一种方案,不带iframe的组件正常使用keep-alive,带iframe的组件开始时隐藏,切换到带iframe的组件时,隐藏其他不带iframe的组件,显示带iframe的组件,通过v-if将iframe的显示做成懒加载形式的,只有在用户进入相应的页面时才触发渲染,在渲染完毕后再通过v-show去控制界面在切换时的显示与隐藏
<keep-alive>
<component
:is="curComponents"
v-show="noIframe"
/>
</keep-alive>
<component
:is="iframeComponent"
v-if="iframeLoaded"
v-show="!noIframe"
/>
//使用keep-alive缓存不了iframe,需要单独拎出来
const iframeComponent = ref(null);
/**
* 隐藏带iframe的组件
*/
const noIframe = ref(true);
/**
* 判断iframe组件是否已经加载
*/
const iframeLoaded = ref(false);
const curComponents = ref(test1);
//切换菜单
const handleNodeClick = (data) => {
const componentsIds = {
//正常的组件
1: test1,
// 带iframe的组件
2: test2,
};
if (componentsIds[data.id]) {
if (data.id === 2) {
noIframe.value = false;
iframeLoaded.value = true;
iframeComponent.value = componentsIds[data.id];
} else {
noIframe.value = true;
curComponents.value = componentsIds[data.id];
}
}
};