javascript跨域之postMessage

版权声明:本文为博主原创文章,未经博主允许不得转载。

 

前言

前面我们说了window.name的跨域,今天我们来讲一下postMessage跨域。

定义

在HTML5中新增了postMessage方法,postMessage可以实现跨文档消息传输(Cross Document Messaging),Internet Explorer 8, Firefox 3, Opera 9, Chrome 3和 Safari 4都支持postMessage。
该方法可以通过绑定window的message事件来监听发送跨文档消息传输内容。

语法

window.postMessage(msg,targetOrigin)

参数说明

msg:要传递的数据,该参数可以是JavaScript的任意基本类型或可复制的对象

targetOrigin:指定目标窗口,注意是目标窗口,不是本窗口,一个完整的域为:协议+主机+端口号[+URL],URL会被忽略,所以可以不写,形如: http://www.midaoi.com:80/ ,postMessage()方法只会将message传递给指定窗口,当然如果愿意也可以建参数设置为”*“,这样可以传递给任意窗口,如果要指定和当前窗口同源的话设置为”/“。

正文

postMessage要通过window对象调用!这里的window不只是当前window,大部分使用postMessage的时候,都不是本页面的window,而是其他网页的window,就像前面所讲的window.name一样,如:iframe的contentWindow,通过window.open方法打开的新窗口的window。

发送postMessage消息

下面的代码示范了如何向目标域发送消息:

1
2
3
window.onload=function(){
window.postMessage('要发送的消息','*');
}

获取postMessage消息

如果想要对postMessage传递消息进行操作,我们需要一个onmessage事件,如:

1
2
3
window.addEventListener('message',function(e){
console.log(e.origin,e.data) //e.data就是传递过来的数据,
});

我们来看一下这个event对象里的内容:

event对象内容

注意这里的几个属性:
data:传递来的message消息
source:发送消息的窗口对象
origin:发送消息窗口的源(协议+主机+端口号)

通过这些属性你还可以判断一下e.source和e.origin是不是正确来源,这样显得更加安全,不是吗?

我们还可以用同样的方法往回发信息,很有意思吧!

postMessage跨域

现在我们来看一下postMessage如何去实现跨域的,同样的我们先来一个iframe让他指向B域名,添加如下代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<style>
#ifa {
border: none;
}
#txt {
width: 200px;
padding: 45px 0;
border: none;
float: left;
color: #fff;
margin: 0 15px;
text-align: center;
background: blue;
}
</style>
</head>
<body>
<div id="txt"></div>
<iframe id="ifa" src="B域名的demo2.html"></iframe>
<script>
window.onload = function() {
window.frames[0].postMessage('new', '*');
}
window.addEventListener('message', function(e) {
var result = e.data;
document.getElementById('txt').innerHTML = result;
}, false);
</script>
</body>
</html>

来看一下B域名的demo2文件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<style>
#txt{
width: 200px;
padding: 50px 0;
border: none;
color: #fff;
text-align: center;
background: red;
}
</style>
<div id="txt" onclick="changeTxt();">点我就可以改变postMessage传过来的值了,不信就试试看!
</div>
<script>
var box=document.getElementById('txt');
window.addEventListener('message',function(e){
if(e.source!=window.parent) return;
var result=box.innerHTML;
window.parent.postMessage(result,'*');
},false);
function changeTxt () {
var result=box.innerHTML;
if(result=='new'){
result='old';
}else{
result='new';
}
box.innerHTML=result;
window.parent.postMessage(result,'*');
}
</script>
</body>
</html>

来看一下点击之后的效果:

未点击:
未点击
点击一次:
点击一次
点击二次:
点击两次

总结

h5中新增的方法,可以实现跨文档消息传输,通过绑定window的message事件来监听发送跨文档消息传输内容,兼容高级浏览器以及IE8+,为了考虑兼容问题建议使用message事件时,判断下attachEvent,h5的另一个API——web workers也应用的此传递方法。