postMessage
接口允许窗口之间相互通信,无论它们来自什么源。
因此,这是解决“同源”策略的方式之一。它允许来自于 marh.com
的窗口与来自于 qq.com
的窗口进行通信,并交换信息,但前提是它们双方必须均同意并调用相应的 JavaScript 函数。这可以保护用户的安全。
这个接口有两个部分。
1 postMessage
想要发送消息的窗口需要调用接收窗口的 postMessage
方法。换句话说,如果我们想把消息发送给 win
,我们应该调用 win.postMessage(data, targetOrigin)
。
参数
data
要发送的数据。可以是任何对象,数据会被通过使用“结构化序列化算法(structured serialization algorithm)”进行克隆。IE 浏览器只支持字符串,因此我们需要对复杂的对象调用 JSON.stringify
方法进行处理,以支持该浏览器。
targetOrigin
指定目标窗口的源,以便只有来自给定的源的窗口才能获得该消息。
// <iframe src="http://127.0.0.1:8080/2.html" name="example" />
let win = window.frames.example;
win.postMessage("message", "http://127.0.0.1:8080");
2 onmessage
为了接收消息,目标窗口应该在 message
事件上有一个处理程序。当 postMessage
被调用时触发该事件(并且 targetOrigin
检查成功)。
event 对象具有特殊属性:
-
data
从postMessage
传递来的数据。 -
origin
发送方的源,例如http://javascript.info
。 -
source
对发送方窗口的引用。如果我们想,我们可以立即source.postMessage(...)
回去。
要为 message
事件分配处理程序,我们应该使用 addEventListener
,简短的语法 window.onmessage
不起作用。
window.addEventListener("message", function(event) {
console.log(event)
if (event.origin != 'http://http://127.0.0.1:8080') {
// 来自未知的源的内容,我们忽略它
return;
}
if (window == event.source) {
// chrome 下, 页面初次加载后会触发一次 message 事件, event.source 是 window 对象
// 此时 event.source.postMessage 会形成死循环
// 因此,要跳过第一次的初始化触发的情况
return
}
console.log( "received: " + event.data );
// 可以使用 event.source.postMessage(...) 向回发送消息
event.source.postMessage('i am 2.html')
}, source);