Window.postMessage() HTML5 跨域解决方案
又是倒霉的跨域 T T , 有多少人死在了“说出你知道的跨域解决方案,越多越好?”这个面试问题上。
今天和大家说说,HTML5提供的一个跨域解决方案,Window.postMessage , 它足够易学好用,会让你眼前一亮。但是往往大多数情况下,都不会让人一直笑下去,俗话说道高一尺魔高一丈,这个方法同样也会被HTTP的一些协议所限制着,比如X-Frame-Options:SAMEORIGIN
,不过好在大多数情况下,情况不至于这么糟糕。下面进入正题:
Window.postMessage 提供了一种安全的跨域通讯方案。
语法
语法分为两部分,发和收,其实都很简单。
发送
otherWindow.postMessage( message , origin [ , transfer] )
* otherWindow
跨域的window对象的引用,比如iframe、window.open创建的对象等。
* message
发给跨域对象的消息,可以是string,object,number等对象
* origin
指定消息发送的域名,可以使用通配符 *
接收
我们可以监听window 的 "message" 事件来获取到传递过来的值,例如:
window.addEventListener('message',receiveMessage,false);
function receiveMessage(event){
// ...
}
接收到的event包含下面几个重要的属性:
* data
传递过来的信息。
* origin
发送消息的域名,包含了协议和端口(如 https://developer.mozilla.org:443),通常情况下 默认端口会被省略,例如 https://www.google.com 意味着省略了端口443 , http://www.google.com 省略了端口 80。
* source
发送数据的window的引用,例如b域名收到a域名的消息,此时的source指的是a域名的window,你可以通过它来实现双向通讯。
举例:
好了,终于可以举个例子了,(等等我的糖炒板栗呢?)
示例页面:
示例代码:
http://jsbin.com/wecoqi/9/edit?html,js
http://jsbin.com/qetuwicebo/9/edit?html,js
代码解释
用户打开A页面,点击Open Window按钮,打开一个新的B页面(由于资源有限,Demo中用同域作为演示), 回到A页面点击 push message 按钮 ,发送你好到B页面,同时收到B页面的反馈。 这时候回到B页面,就能看到B页面的收到的消息了。
具体代码如下。
A页面
//获取按钮以及显示文本的DOM
var openWindow = document.getElementById('open');
var pushMessage = document.getElementById('push');
var messageBox = document.getElementById('message');
var newWin;
//Open Window 按钮事件
openWindow.addEventListener('click',function(){
//点击之后,打开一个新的窗口,并获得该窗口的引用
newWin = window.open('http://jsbin.com/qetuwicebo');
})
pushMessage.addEventListener('click',function(){
//点击发送消息按钮,发送你好到新打开的窗口
//注意第二参数是接收消息的域名,虽然可以用*匹配所有的域名,
//但是在生产环境中,强烈建议写成真实的域名,以防不必要的攻击
newWin.postMessage('你好','*');
//
messageBox.innerHTML= messageBox.innerHTML+'发送了消息“你好“,请移步新打开的页面查看收到的消息'
})
//监听message事件,已接收其他页面发来的信息
window.addEventListener('message',function(event){
messageBox.innerHTML= messageBox.innerHTML+'<br>收到了回复:'+event.data
})
B页面
//监听message事件
window.addEventListener("message", receiveMessage, false);
function receiveMessage(event ){
//注意,在生产环境中,一定要验证event.origin,以避免潜在的安全问题
var html='event.data: '+event.data+'<br>';
html += 'event.origin: '+event.origin+'<br>';
html += 'event.source: '+event.source+'<br>';
document.getElementById('message').innerHTML= html;
//收到消息之后我们会给,父页面发送一条回复
//event.source可以获取到消息来源页面的引用
event.source.postMessage('hi,我来之新打开的页面,我收到你post的消息了',event.origin);
}
结尾
不想写结尾,但是,如果不写 @Robin Ma 又要说我的文章结尾太唐突了。 好吧,这里是结尾,就这样。 对了,记得回复哦,这是最好的鼓励 ~ :)