关于iframe在vue中应用的问题

关于iframe在vue中应用的问题

背景是一个vue3.0的个人博客,由于没有支持vue3.0的md展示手段(具体是vue-template-compiler版本太低目前最高2.6.12,而要求vue必须与其版本相同),所以我的解决方法是先将md文件转换成html文件然后由iframe直接导入页面。

iframe的宽高无法根据内容撑开

网上查阅了许多解决方法(其中多数是讲iframe自适应页面而非自适应内容),但基本思路都是***获取到iframe 内容的body宽高,重新赋值给iframe本身,但问题就出在***什么时候获取iframe宽高,vue的生命周期在iframe中完全失效,于是我的解决思路如下

  1. 首先利用点击文章列表这一过程,在每次点击后获取iframe body的宽高赋值给iframe本身
<iframe
 style="width: 100%; height: 100%"
 scrolling="no"
 class="iframe"
 :src="item.path"
 frameborder="0"
>iframe>
  1. 要强调的是一定是点击结束后,即新文章已经显示后才能后去到body的宽高
  2. 如果你也用了ui组件提供的click回调函数,并在其中做这件事,一定要使用this.$nextTick{}将你要做的事放到回调的最后执行
methods: {
//ui组件给的回调
   handleClick(tab, event) {
   //参数详见elemntui的tabs,这里只用到了tab.index获取点击文章的序号
     const oIframe = document.getElementsByClassName("el-tabs__content")[0]
       .children;

     const iframe = oIframe[tab.index].children[0].children[1].children[0];
     //以上都是找元素节点iframe的过程可忽略(因为用了v-for所以找起来会有点麻烦)
     this.$nextTick(function () {
       iframe.style.height =
         iframe.contentWindow.document.body.offsetHeight + "px";
         //contentWindow中有iframe对应网页的全部信息,包括windows、document等
     });
   },
 },
  1. 现在,点击文章列表的单个文章,文章的大小应该已经正常了,但页面首次加载时默认文章大小怎么办呢(我曾想过调用一次点击函数来模拟点击一次默认文章,但ui组件让我没有这个机会,后来想想这也确实不是什么好方法)
  2. 为了解决这个问题,我又重新回到vue的mounted的函数,但无论如何也获取不到body正确的高度,用this.$nextTick{}只会获取到最终iframe默认的宽高,这时vue的生命周期又失效了,为了找到这个时间点,只能再次求助原生的dom了
mounted() {
    const oIframe = document.getElementsByClassName("el-tabs__content")[0]
      .children;
    //该处dom操作的耦合性较高,待优化
    const iframe = oIframe[0].children[0].children[1].children[0];
    //以上都是找元素节点iframe的过程可忽略(因为用了v-for所以找起来会有点麻烦)
    this.$nextTick(function () {
      iframe.contentWindow.window.onload = () => {
        if (iframe.contentWindow.document.readyState == "complete") {
          iframe.style.height =
            iframe.contentWindow.document.body.offsetHeight + "px";
        }
      };
    });
  },
  1. 这个时间点很玄学,所以确切的说是点击文章列表后iframe完全加载完成后,才能获取到body的宽高,否则即使能够获取到body标签而且body内容都已加载完成,body的offsetHeight依然是0,最后我找到了iframe.contentWindow.document.readyState == "complete"这个代表iframe页面加载完成的标志,在其为”complete“后马上获取body的宽高,赋值,即可

你可能感兴趣的:(vue3项目的艰辛历程)