跨窗口通信

46 阅读2分钟

iframe 标签承载了一个单独的嵌入的窗口,它有自己的 documentwindow

otherWindow.postMessage(message, targetOrigin, [transfer])

postMessage

postMessage 接口允许窗口之间相互通信,无论它们来自什么源。

父页面地址:a.index.com

子页面地址:b.index.com

父页面通过iframe引入子页面
<!-- a.index.html -->
<h1>父页面</h1>
<iframe id="iframe" src="http://b.index.com"></iframe>
父页面向子页面发送一条消息
const iFrame = document.getElementById('iframe')
<!-- 需要等到iframe中的子页面加载完成后才发送消息,否则子页面接收不到消息 -->
iFrame.onload = function(){
  <!-- iFrame.contentWindow获取到iframe的window对象 -->
  iFrame.contentWindow.postMessage('父页面发送的消息','http://b.index.com');
}
子页面接收父页面的消息
window.addEventListener('message',e=>{
    <!-- 对消息来源origin做一下过滤,避免接收到非法域名的消息导致的xss攻击 -->
    if(e.origin==='http://a.index.com'){
        console.log(e.origin) //父页面URL,这里是http://a.index.com
        console.log(e.source) // 父页面window对象,全等于window.parent/window.top
        console.log(e.data)  //父页面发送的消息
    }
},false)
子页面向父页面发送一条消息
window.parent.postMessage('子页面发送的消息','http://a.index.com')
父页面接收子页面的消息
window.addEventListener('message',e=>{
    <!-- 对消息来源origin做一下过滤,避免接收到非法域名的消息导致的xss攻击 -->
    if(e.origin==='http://b.index.com'){
        console.log(e.origin) //子页面URL,这里是http://b.index.com
        console.log(e.source) // 子页面window对象,全等于iframe.contentWindow
        console.log(e.data) //子页面发送的消息
    }
},false)
  • window.postMessage中的window指的是你想发送跨域消息的那个窗口(你需要通信的目标窗口),而不是自身窗口的window
  • 父页面中:父页面向子页面发送跨域信息,window就是在父页面中嵌入的iframe指向的子页面的window,即:iFrame.contentWindow
  • 子页面中:子页面想父页面发送跨域信息,window就是父页面的window,在这里因为子页面是嵌入到父页面中的,对于子页面来讲,window就是top或者parent
  • 需要等到iframe中的子页面加载完成后才发送消息,否则子页面接收不到消息
  • 在监听message事件时需要判断一下消息来源origin