2019-05-09 postMessage的使用方法:

HTML5提出了一个新的用来跨域传值的方法,即postMessage 幸运的是IE8就开始支持了。

我们假设有两个网站,1.com与2.com,我在1.com的页面上通过iframe或window.open或超链接打开了一个2.com的网页,此时我要在2.com上做操作的时候,给1.com传值,让1.com有所变化。这个过程就是个跨域的过程。

比如,你的父页面有个函数叫callback,然后你子页面本可以这样调用:window.opener.callback(),同域时能成功,跨域时就没有权限了。

但是,此时你调用window.opener.postMessage(),却可以成功。

postMessage语法
window.postMessage(msg,targetOrigin)

这里我要专门说一下postMessage要通过window对象调用!因为这里的window不只是当前window,大部分使用postMessage的时候,都不是本页面的window,而是其他网页的window!如:

1,iframe的contentWindow

2,通过window.open方法打开的新窗口的window

3,window.opener

如果你使用postMessage时没有带window,那么,当然,你就是用的本页面的window来调用了它。

参数说明
msg
这就是要传递的消息了。它可以是一切javascript参数,如字符串,数字,对象,数组,而不是和json一样只局限于字符串,很强大吧?

targetOrigin
这个参数称作“目标域”,注意啦,是目标域不是本域!比如,你想在2.com的网页上往1.com网页上传消息,那么这个参数就是“http://1.com/”,而不是2.com.

另外,一个完整的域包括:

协议,主机名,端口号。如:http://g.cn:80/

获取postMessage传过来的消息
要对postMessage传来的消息进行处理,就要在页面上加一个onmessage事件。如:

window.addEventListener('message',function(e)

{

console.log(e.origin,e.data)

;

alert('有数据传来了!')

;

}
)

要注意:最好是通过addEventListener或attachEvent来加入onmessage事件,而不要直接window.onmessage=function(){},因为有的浏览器这样加会识别不了(如低版Firefox)

这个onmessage事件接受一个参数,就是代码里的e,实际上他就是一个event对象。但他里面有很明显的3个参数与其他event对象不一样,即:

1,data:顾名思义,是传递来的message

2,source:发送消息的窗口对象

3,origin:发送消息窗口的源(协议+主机+端口号).比如从2.com往1.com发了消息,那么1.com收到消息时,e.origin就是2.com

最重要的就是data了,你可以用e.data取得他,然后做后续操作了。不过为了安全,你最好先判断一下e.source和e.origin是不是正确来源,再作操作。

完整的postMessage流程示例
接着刚才的例子来,我着重讲一个弹窗给父页面传消息的例子。

我们的父页面叫1.com,他上面有关键代码是:

window.addEventListener('message',function(e)

{

console.log(e.origin,e.data)

;

alert('子页面有数据传来了!')

;

}
)

就这么简单。而弹出窗口(2.com)上的代码是:

vardomain='http://1.com/';

window.opener.postMessage({obj:'I am a obj'},
domain

)

就是其他应用场景的例子
1,必须要说明:通过超链接打开的新窗口也能用window.opener来访问其父页面,代码跟上面一样

2,iframe的例子

父页面:

varo=document.getElementsByTagName('iframe')[0]

;

o.contentWindow.postMessage('Hello World',"*");
//向框架页传消息

被框架包裹的子页面:

window.addEventListener('onmessage',function(e)

{

if(e.domain=='1.com')

{

if(e.data=='Hello World')

{

e.source.postMessage('Hello',"*");

//反过来向父页面传消息

}else

{

alert(e.data)

;

}

}

})
;

这个例子充分说明了postMessage是双向的。

3,window.open一个窗口,然后向他传消息

父页面:

vardomain2='http://2.com/'

;

varwin=window.open(domain2+'Portal/2.com.html','wwwwwwww'

)

setTimeout(function()

{

win.postMessage('ddddddddd',domain2

)

},2000
)

子页面:

window.addEventListener('message',function(e)

{

console.log(e.origin,e.data

)

}
)

要注意父页面中的setTimeout,也就是要延迟传消息,因为子页面不可能瞬间加载完成,他的onmessage事件也就没初始化成功,这时给他传消息,当然是收不到的了。

后记
1,IE8+虽然支持postMessage,但只支持iframe的方式,window.open打开的新窗口之间,没法用。直到IE10才有相关改进

2,如何在本地模拟跨域呢?在hosts文件里加入:

127.0.0.1 1.com127.0.0.1 2.com

就可以模拟出2个不同的域名了。

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 作者:阮一峰 日期:2016年4月 8日 浏览器安全的基石是"同源政策"(same-origin policy)。...
    起名字太累阅读 660评论 0 1
  • 1. 什么是跨域? 跨域一词从字面意思看,就是跨域名嘛,但实际上跨域的范围绝对不止那么狭隘。具体概念如下:只要协议...
    w_zhuan阅读 532评论 0 0
  • 浏览器安全的基石是”同源政策”(same-origin policy)。很多开发者都知道这一点,但了解得不全面。 ...
    强哥科技兴阅读 242评论 0 0
  • 1. 什么是跨域? 跨域一词从字面意思看,就是跨域名嘛,但实际上跨域的范围绝对不止那么狭隘。具体概念如下:只要协议...
    他在发呆阅读 830评论 0 0
  • 一、概述 1.1 含义 1995年,同源政策由 Netscape 公司引入浏览器。目前,所有浏览器都实行这个政策。...
    会飞的贼er阅读 452评论 0 2