用postMesage实现跨域,并解决Failed to execute 'postMessage' on 'DOMWindow'

广告

阿里招聘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
角色:接收方

 

对应的脚本

window.addEventListener( "message",
		function(e){
			alert(e.data);
		},false);

对应的e就是我们上面讲得messageEvent,它是通过参数传递到我们的监听函数的。

iframe页面

url:http://localhost:8080/boring.html
角色:发送方

 

对应的脚本

document.getElementById("btn").onclick = function() {
        //localhost:8020就是发送的url的源
        //记住要写top.postMessage或者是parent.message,对于top和parent区别,google一大堆
        //千万不要写window.postMessage
	top.postMessage("hello", "http://localhost:8020");
}

这样子我们的代码就完成了。

有图有真相

主页面:

用postMesage实现跨域,并解决Failed to execute 'postMessage' on 'DOMWindow'_第1张图片

只要点击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?

你可能感兴趣的:(html5,postMessage)