postMessage
与message
postMessage
postMessage(data,origin)
方法允许来自不同源的脚本采用异步方式进行通信,可以实现跨文本档、多窗口、跨域消息传递。接受两个参数:
data
:要传递的数据,HTML5规范中提到该参数可以是JavaScript的任意基本类型或可复制的对象,然而并不是所有浏览器支持任意类型的参数,部分浏览器只能处理字符串参数,所以在传递参数时需要使用JSON.stringify()
方法对对象参数序列化。origin
:字符串参数,指明目标窗口的源,协议+主机+端口号[+URL],URL会被忽略,所以可以不写,只是为了安全考虑,postMessage()方法只会将message传递给指定窗口,当然也可以将参数设置为"*"
,这样可以传递给任意窗口,如果要指定和当前窗口同源的话设置为"/"
。
postMessage 可用于解决以下方面的问题:
- 页面和其打开的新窗口的数据传递
- 页面与嵌套的 iframe 消息传递
- 多窗口之间消息传递
message
当调用 postMessage() 方法的时候,在目标窗口的Window对象上就会触发一个 message 事件
跨域通信
两个相同域的iframe,可以用localStorage存储数据,有一个页面需要用轮询获取
两个不同域的iframe,可以用父页面做转发,实现消息通信
- 子页面(iframe1、iframe2)发送的消息,mian.html可以接收到
main
// 3.父页面接收消息,并发送到iframe2
window.addEventListener('message',(event)=>{
if(!event.data.from || event.data.from !== 'iframe1'){
return
}
console.log('%c 2.父页面接收消息,并发送到iframe2','font-size:16px;color:#fe2d46;')
console.log('main获取到的消息数据:',event.data)
let ifWin1 = window.frames[1]
ifWin1.postMessage(event.data,'*')
})
// 1.父页面发送消息到iframe1
function sendMsg(){
let ifWin = window.frames[0]
let msg = {from:'主页'}
ifWin.postMessage(msg,'*')
}
iframe1
window.addEventListener("message", (event) => {
console.log('%c 1.父页面发送消息到iframe1,iframe1接收后发送到父页面','font-size:16px;color:#fe2d46;')
console.log('iframe1获取到的消息', event.data)
window.top.postMessage({from:'iframe1',data:{
user:'abc',
token:'92743gjg4389hkhmc',
source:event.data.from || ''
}},'*')
})
iframe2
window.addEventListener("message", (event: any) => {
console.log('%c 3.iframe2接收到从iframe1发送的消息','font-size:16px;color:#fe2d46;')
console.log('iframe2获取到的消息', event.data)
})
效果
父页面与嵌套iframe之间的消息传递示意图
上面的跨域通信示例,不给iframe2
发消息的话,就是如下图所示了。