记录一次父页面与子页面交互通信的实践

488 阅读2分钟

我们经常会遇到一个页面内嵌套个iframe的情况,那它们之间怎么相互通信呢?

Answer: 在这里介绍两种方式,第一种是postMessage,它是可以让内外页面相互交流的,但是这是有条件的,具体怎么做,请继续往下看。第二种是通过给iframe的src加hash或者query来把外层数据传给内层。

在进入正题前,先来介绍一下同源策略的概念。

  • 浏览器的同源策略:如果两个页面的协议,端口(如果有指定)和主机都相同,则两个页面具有相同的源。它限制了从同一个源加载的文档或脚本如何与来自另一个源的资源进行交互。这是一个用于隔离潜在恶意文件的重要安全机制。所以当一个网页请求不同源的资源时,会报跨域错误,解决它的方式有很多,比如可以让后端在响应头处设置Access-Control-Allow-Origin:* 或者使用jsonp, iframe等。 附上链接: segmentfault.com/a/119000001… juejin.cn/post/684490…

下面进入正题:

1. 通过postMessage让子向父通信,可跨域

向父发消息,在父中接收

// inside the parent window http://haha.com:8000
window.addEventListener('message', function(e){
    let data = e.data;
    if (data.type === 'XXX') {
        // Do something
    }
})
// inside iframe https://iframe.com:8080
let transferData = { //可以自定义
    type: 'XXX'
}
top.postMessage(transferData, '*')

2. 通过postMessage让父与子通信,需同域

向子发消息,在子接受。
P.S.如果跨域的话,document.getElementById('iframeId').contentWindow就会报错。

//inside the parent window http://haha.com:8000

<iframe onload="iframeObLoad()" id="iframeId" ></iframe>
// after the iframe is loaded,you can send postMessage
function iframeOnLoad() {
    let iframeWin = document.getElementById('iframeId').contentWindow;
    let transferData = { //可自定义属性
        type: 'XXX'
    }
    iframeWin.postMessage(transferData, '*')
}
// inside iframe http://haha.com:8000
window.addEventListener('message', function(e){
    let data = e.data;
    if (data.type === 'XXX') {
        // Do something
    }
})

3. 通过iframe的src来实现父与子通信,可跨域

在给iframe赋值时,可以在最后添加用于父子通信的key and value pairs 或者 hash。在iframe里面在去解析url,获取所需要的值。