keep-alive 无法缓存 iframe 解决方案

3,133 阅读2分钟

参考

# 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页还是刷新的。

解决方案

  1. 网上的方案是使用路由的解决方案:切换不含iframe的界面时使用vue路由,在切换含iframe页的界面时利用v-show来控制显示隐藏,使iframe的节点不被删除,以此来防止界面节点被重新更新,从而达到保存iframe节点数据的效果
  2. 我考虑了另一种方案,不带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];
    }
 
  }

};