vue通过iframe加载本地vue页面

软件发布|下载排行|最新软件

当前位置:首页IT学院IT技术

vue通过iframe加载本地vue页面

tianyue_yuan   2022-09-29 我要评论

通过iframe方式加载本地的vue页面

也是在实际的项目中碰到一个奇葩的需求,用vue,居然还要用到iframe,真是脑壳大,试了好多次最后才找到了正确的方法。

总共有三种方法吧

iframe方式加载本地的vue页面的第一种方法

就是直接使用具体的页面地址:http://127.0.0.1:8080/Index

<iframe
  src="http://127.0.0.1:8080/Index"
  id="frames"
  frameborder="0"
  sandbox="allow-forms allow-scripts allow-same-origin allow-popups"
  style="height: 100%; width: 100%"
></iframe>

iframe方式加载本地的vue页面的第二种方法

跟第一种方法类似,就是将127改为了localhost

<iframe
  src="http://localhost:8080/Index"
  id="frames"
  frameborder="0"
  sandbox="allow-forms allow-scripts allow-same-origin allow-popups"
  style="height: 100%; width: 100%"
></iframe>

不过,注意一下,第一种和第二种方法只能在本地访问时生效,当打包部署到线上后,就会出现页面找不到的问题,不能部署那用处少了太多,这时要用第三种方法

iframe方式加载本地的vue页面的第三种方法

第三种方法跟页面中用相对路径引用图片的方式差不多,就是:…/index,这里的路径的路由中的路径

<iframe
  src="../index"
  id="frames"
  frameborder="0"
  sandbox="allow-forms allow-scripts allow-same-origin allow-popups"
  style="height: 100%; width: 100%"
></iframe>
// 或者是像这样的路径
<iframe
  src="../#/index"
  id="frames"
  frameborder="0"
  sandbox="allow-forms allow-scripts allow-same-origin allow-popups"
  style="height: 100%; width: 100%"
></iframe>

像第三种方法,就可以实现在打包部署在线上时,正确访问到相应的页面。

不过注意一下,当在本地打包成功后,在本地进行测试时,会出现嵌入的页面不是你想要的页面,而是自己项目的树形文件结构。

这是正常的,当部署到线上后,就是正常的页面啦

关于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中完全失效,于是我的解决思路如下

首先利用点击文章列表这一过程,在每次点击后获取iframe body的宽高赋值给iframe本身

<iframe
 style="width: 100%; height: 100%"
 scrolling="no"
 class="iframe"
 :src="item.path"
 frameborder="0"
></iframe>

要强调的是一定是点击结束后,即新文章已经显示后才能后去到body的宽高

如果你也用了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等
     });
   },
 },

现在,点击文章列表的单个文章,文章的大小应该已经正常了,但页面首次加载时默认文章大小怎么办呢(我曾想过调用一次点击函数来模拟点击一次默认文章,但ui组件让我没有这个机会,后来想想这也确实不是什么好方法)

为了解决这个问题,我又重新回到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";
        }
      };
    });
  },

这个时间点很玄学,所以确切的说是点击文章列表后iframe完全加载完成后,才能获取到body的宽高,否则即使能够获取到body标签而且body内容都已加载完成,body的offsetHeight依然是0,最后我找到了iframe.contentWindow.document.readyState == "complete"这个代表iframe页面加载完成的标志,在其为”complete“后马上获取body的宽高,赋值,即可 

以上为个人经验,希望能给大家一个参考,也希望大家多多支持。 

Copyright 2022 版权所有 软件发布 访问手机版

声明:所有软件和文章来自软件开发商或者作者 如有异议 请与本站联系 联系我们