vue中使用iframe以及通信问题

499 阅读2分钟

需求背景

  • App中内嵌的是h5页面,属于第三方开发,现我们需要增加一个页面,需要嵌入到App内部,也就是说需要嵌入第三方h5页面中。于是我们和第三方商量使用iframe进行嵌入,就有了今天要考虑的使用和通信问题

开始查询文档

  • irfame使用:
<iframe id="iframe" src="xxxx" style="height: 100vh" width="100%" frameborder="0">
        您当前的浏览器不支持页面上的功能,请升级您当前的浏览器版本或使用谷歌浏览器访问当前页面
</iframe>

两种通信方式

parent 和 iframe.contentWindow方式代码

// 父调用子的方法:
document.getElementById("myIframe").contentWindow.iframe的属性方法

// 子调用父的方法:
window.parent.iframe父的属性方法

使用 postMessage 进行通信

// 父给子发消息
document.getElementById("iframe").contentWindow.postMessage(JSON.stringify(data), "*")

// 子监听父的消息
window.addEventListener("message", () => {});

// 子发给父消息: 可通过window的属性找到对应的父(这里的parent表示直接上一级的父)
window.parent.postMessage(data, "*");  

// 父监听子消息:
window.addEventListener("message", () =>{});

优缺点比较:

  1. 方式一 parent 和 iframe.contentWindow 方式 适合 同域 下的操作,否则跨域

  2. 方式二 postMessage 进行通信 可以通过监听解决跨域问题,但是需要 iframe 内外的协作

完整代码

父页面

<template>

    <iframe id="iframe" src="http://192.168.1.1:8081" style="height: 100vh" width="100%" frameborder="0">
        您当前的浏览器不支持页面上的功能,请升级您当前的浏览器版本或使用谷歌浏览器访问当前页面
    </iframe>

</template>
<script setup lang="ts">
import { onMounted } from "@vue/runtime-core";
onMounted(() => {
    const Iframe: any = (document.getElementById('iframe') as HTMLIFrameElement).contentWindow;
    const IframeDom: any = document.getElementById('iframe');
    // 父页面向子页面传参
    const data = {
        code: 200,
        token: 'xxxxxx'
    }
    IframeDom.onload = () => {
        Iframe.postMessage(data, 'http://192.168.1.1:8081');
    };
})

  // 父页面接口子页面的传值
  window.onload = () => {
    window.addEventListener('message', event => {
      console.log(event);
  })
 }
</script>
<style>
* {
    margin: 0 0;
    padding: 0 0;
}
</style>

子页面

<script setup>
  // 子页面获取父页面传值
    window.onload = () => {
        window.addEventListener('message', event => {
            if (event.data && event.data.token) {
               获取到你想要的值之后就可以做一些后续操作了
            }
        });
    };
    
 // 子页面向父页面传参,原理相同
 const data = {
    aa:123
 }
 window.parent.postMessage(data, 'http://192.168.1.1:8080');
</script>

总结

遇到的坑:

  • 协议问题,父页面协议是http可以打开子页面的协议http和https,父页面的协议https可以打开子页面https,但是打不开子页面协议http。
  • 注册监听message事件多次执行问题,对于一些是tab切换显隐藏打开iframe的场景,要注意移除监听事件,防止每次切换多次注册,移除事件方法window.removeEventListener('message',myFunction)