postMessage实现iframe之间通信

490 阅读2分钟

有时候会碰到以内嵌 iframe 的方式来对接其他项目,也是为了方便接入其他组已经写好(未写好)的网页,毕竟有时候都不愿意暴露自己的源代码是吧,因此就可能使用到了 postMessage 实现 iframe 之间的交互,当然也有很多其他场景,就不多说了

postMessage(data,origin)方法允许来自不同源的脚本采用异步方式进行通信,可以实现跨文本档、多窗口、跨域消息传递。接受两个参数:

  • data:要传递的数据,HTML5规范中提到该参数可以是JavaScript的任意基本类型或可复制的对象,然而并不是所有浏览器支持任意类型的参数,部分浏览器只能处理字符串参数,所以在传递参数时需要使用JSON.stringify()方法对对象参数序列化。
  • origin:字符串参数,指明目标窗口的源,协议+主机+端口号[+URL],URL会被忽略,所以可以不写,只是为了安全考虑,postMessage() 方法只会将 message 传递给指定窗口,当然也可以将参数设置为"*",这样可以传递给任意窗口,如果要指定和当前窗口同源的话设置为"/"

我们以 iframe 为子页面,以当前页面为主页面,阐述他们的交互

父页面接收消息,并发送到iframe

window.addEventListener('message',(event)=>{
    console.log("收到来自子页面页面的消息", event.data)
})

//获取iframe对象,需要加载完毕才能正常交互
document.getElementById('myIframe').onload = function() {
    iframe.contentWindow.postMessage('Hello, I am the main page!', '*');
};
const iframe = document.querySelector('iframe')
iframe.postMessage("我是父页面发送的消息", "*")

子页面 iframe 接收消息和发送消息

//子页面也可以等window加载完毕之后再监听发送消息
window.onload = () => {}

//接受消息,监听信息
window.addEventListener("message", (event) => {
   console.log("收到来自父页面的消息", event.data)
   if (event.origin === "http://juejin.cn") { 
       // 确保消息来源可靠,也可以再添加数据内的某些参数进行验证
        console.log("Received data", event.data);
        
        //向父类发送消息
        event.source.postMessage('我是子页面发送的消息', '*');
    }
})

//可以单独发消息给父页面
window.parent.postMessage('我是子页面发送的消息', '*');

上面只是单纯的主页面对一个 iframe 子页面,很简单,如果有多个 iframe 子功能格子独立,他们被一个统一的主模块引入,他们之间怎么交互呢,很简单,就让主模块转发一下即可