需求背景
- App中内嵌的是h5页面,属于第三方开发,现我们需要增加一个页面,需要嵌入到App内部,也就是说需要嵌入第三方h5页面中。于是我们和第三方商量使用iframe进行嵌入,就有了今天要考虑的使用和通信问题
开始查询文档
- irfame使用:
<iframe id="iframe" src="xxxx" style="height: 100vh" width="100%" frameborder="0">
您当前的浏览器不支持页面上的功能,请升级您当前的浏览器版本或使用谷歌浏览器访问当前页面
</iframe>
-
MDN中的链接:https://developer.mozilla.org/zh-CN/docs/Web/HTML/Element/iframe
-
使用 parent 和 iframe.contentWindow 获取window环境
-
使用 postMessage 进行通信
两种通信方式
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", () =>{});
优缺点比较:
-
方式一 parent 和 iframe.contentWindow 方式 适合 同域 下的操作,否则跨域
-
方式二 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)