浏览器跨域系列(2)- 跨域和postMessage

在跨域和jsonp的文章里面已经介绍了跨域的基本概念,也介绍了jsonp跨域的原理(script标签+服务器和客户端约定好callback)基本写法和jquer封装;本文介绍window.postMessage()的h5接口实现不同窗口不同页面的跨域通信;

  • 可以发送数据
  • 可以通过发送特定的事件名称,在onMessage里面执行回调,类似于angular的emit和on的关系然后操作dom

postMessage()

1
2
3
4
5
6
7
8
9
10
11
12
someWindow.postMessage(data,origin); 

`<iframe id='iframeId' name='iframeName'>如果浏览器不支持,会显示iframe标签之间的文字</iframe>`
`var iframe = window.frames['iframeName']` # 获取iframe.document.getElementById('iframeId')
`iframe.contentWindow` #获取iframe窗口的window对象
`iframe.contentWindow.postMessage('传给爸爸的信息''iframe的域,当然也可以写成*表示任意域')`

# someWindow 接收数据的window
# data 就是传输的数据
# - html5规范中提到该参数可以是JavaScript的任意基本类型或可复制的对象
# - 并不是所有浏览器都做到了这点儿,部分浏览器只能处理字符串参数,最好JSON.stringify()方法对对象参数序列化
# origin 字符串参数,指明目标窗口的源,当然如果愿意也可以将参数设置为"*

MessageEvent的属性

1
2
3
4
5
6
7
8
9
10
11
   someWindow.addEventListener('message',function(e){
console.log(e.source) # 发送消息的窗口对象
console.log(e.origin) # 发送消息窗口的源(协议+主机+端口号)
console.log(e.data) # 是传递来的message
window.parent.postMessage('ok','*')
# 处于安全考虑,需要判断域是不是发送消息的域
if(e.origin === 'xxx.sourceOrigin.com'){
# todo list
window.postMessage('收到了爸爸的信息','爸爸的域')
}
})

示例说明

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
# iframe里面嵌入的儿子页面
<!DOCTYPE html>
<html lang="en">

<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>blog</title>
<script>
window.onload=function(){ // 这个window就是儿子的window对象
window.addEventListener('message',function(e){
console.log(e.source)
console.log(e.data)
console.log(e.origin)
if(e.origin === '爸爸的origin') // 处于安全一定要校验是不是爸爸域发过来的消息
window.parent.postMessage('马上回来爸爸','*') // 给爸爸页面发消息
})
}
</script>
</head>

<body>
<p>我是跨域的儿子页面,在爸爸的iframe里面嵌入的页面</p>
</body>

</html>
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
41
42
43
44
45
46
47
    # 爸爸页面
<!DOCTYPE html>
<html lang="en">

<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>blog</title>
<style>
body {
height: 1000px;
overflow: hidden;
}

#myrame {
box-sizing: border-box
}

#myrame1 {
box-sizing: border-box
}
</style>
<script>
window.onload=function(){
var iframe = document.getElementById("myrame");
var subBut = document.getElementById('buttons');
subBut.addEventListener('click',function(e){
iframe.contentWindow.postMessage('儿子吃饭啦','*');
});
window.addEventListener('message',function(e){
console.log(e.source)
console.log(e.data)
})

}
</script>
</head>

<body>
<iframe name="myiframe" id="myrame" src="b.html" frameborder="1" align="left" width="50%"
height="100%" scrolling="auto">
</iframe>
<button id='buttons'>叫儿子回家吃饭</button>
</body>

</html>
初到贵宝地,有钱的给个钱场,没钱的挤一挤给个钱场