广告
阿里招聘2020届前端实习生,详情可看 https://blog.csdn.net/monkindey/article/details/88960480
前言
看了HTML5的postMessage,觉得好像挺好玩的,突然想要去尝试下,但是前提就是要有两个不同的源
源 = 规则(http/https)+主机(localhost/其他域名)+端口号,只要有一个不一样,那么两个网页就是不同的源,在浏览器会实现javascript的同源策略,对于不同的源是不能通信的,但是HTML5实现了postMessage标准。
配置两个网页不同源
当时看HTML5的postMessage的时候,我就在想端口号不同就可以实现不同源,那我在我主机开两个内置服务器就好啦。当时我是用aptana写HTML5的,我看见它有一个内置web服务器,端口号是8020,可能8080被我的tomcat占用了吧。然后我就想到我的tomcat服务器的端口号是8080。耶!这样子就解决了设置两个网页不同源啦。
理解HTML5 postMessage原理
理解postMessage实现跨文档消息通信其实不是很难,就是发送方用postMessage给接受方一个消息,然后接收方监听message事件,就是事件驱动,通过messageEvent中的data来获取发送方发送的消息,origin来获取发送方所在的源(可以用来屏蔽掉其他源的网页发来的消息)。
开始编写postMessage代码
说说容易,写起来真的很难。我用iframe标签来模拟不同源的两个页面
主页面
url :http://localhost:8020/measurementWeb/html5.html
角色:接收方
<iframe src="http://localhost:8080/boring.html" ></iframe>
对应的脚本
window.addEventListener( "message",
function(e){
alert(e.data);
},false);
对应的e就是我们上面讲得messageEvent,它是通过参数传递到我们的监听函数的。
iframe页面
url:http://localhost:8080/boring.html
角色:发送方
<button id="btn">
press
</button>
对应的脚本
document.getElementById("btn").onclick = function() {
//localhost:8020就是发送的url的源
//记住要写top.postMessage或者是parent.message,对于top和parent区别,google一大堆
//千万不要写window.postMessage
top.postMessage("hello", "http://localhost:8020");
}
这样子我们的代码就完成了。
有图有真相
主页面:
只要点击iframe 中的按钮,那么在主页面就会弹出hello,因为我们已经在子窗口中用postMessage方法发送到主页面,发送的数据是"hello",不清楚请看iframe标签对于的javascript脚本,而我的主页面监听了message事件,设置了监听函数,弹出来e.data就是iframe发送的数据。
问题Failed to execute 'postMessage' on 'DOMWindow'
到了这里本来应该这篇postMessage入门篇已经结束啦,还要写什么呀?我之前说其实说说很容易,写起来有点难,因为我遇见一个bug,困惑了我很久,就是Failed to execute 'postMessage' on 'DOMWindow'
那为什么会出现这个问题?上面在写iframe的脚本时,我提醒了要用top.postMessage,不要用window.postMessage,其实top就是指向iframe最顶层的窗口,在我们这个例子中,因为主页面只内嵌一个窗口,所以对于子窗口top是等于parent,那我们如果用window.postMessage会出现什么问题呢?就会出现上面那个问题。其实是自己想当然了,对于postMessage语法了解不是很深,所以会导致上面的问题。
window.postMessage MDN
otherWindow.postMessage(message, targetOrigin, [transfer])otherWindow: A reference to another window(接收方的引用)
message:Data to be sent to the other window.(要发送到接受方的数据)
targetOrigin:Specifies what the origin of otherWindow must be for the event to be dispatched(接收方的 源,还有必须要有监听message事件)
所以只样子就解决了为什么要用top不用window了,现在发送方是iframe,但是我用的是window就是指iframe的window对象,但是这个不符合postMessage语法,要用到接收方的引用,也就是top.
参考文献
window.postMessage
How do you use window.postMessage across domains?