HTML5的postMessage使用记要

HTML5提出了一个新的用来跨域传值的方法,即postMessage(这个名字太通俗了所以你最好看看是不是自己写过一个同名的把它覆盖了)。幸运的是IE8就开始支持了。

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

如果你对window.open熟,你就会知道通过window.open打开的网页(我们称之为子网页),可以通过window.opener对 象,访问到把它打开的页面(父网页),这样一来,调用父页面的函数就是非常简单的事了。但是,在跨域的条件下,window.opener就成了一个空对 象,“没有权限”,浏览器会这么告诉你。

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

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

关于跨域传值的痛苦我就不多说了,本文只说一些前两天学习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来调用了它。

postMessage的名字很容易误导用户,以为他是用来从一个页面往另一个页面”post”,实际上他和onclick等一样,也只能在本页面定义,本页面处理交互,只是可以从其他页面调用本页面的postMessage.

参数说明

msg

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

targetOrigin

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

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

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

获取postMessage传过来的消息

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

1 window.addEventListener(‘message‘,function (e) { 2 console.log(e.origin,e.data); 3 alert(‘有数据传来了!‘); 4 })

要注意:最好是通过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)上的代码是:

var domain = ‘http://1.com/‘;
window.opener.postMessage({obj:‘I am a obj‘},domain)

还是很简单吧!你看,跨域时本来不能访问的window.opener可以访问了——不过你直接调用父页面的方法还是会失败!就是这么不讲理。

其他应用场景的例子

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

2,iframe的例子

父页面:

var o = 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一个窗口,然后向他传消息

父页面:

var domain2 = ‘http://2.com/‘;
var win = window.open(domain2+‘Portal/2.com.html‘,‘wwwwwwww‘)
setTimeout(function  () {
    win.postMessage(‘ddddddddd‘,domain2)
},2000)

子页面:

1 window.addEventListener(‘message‘,function  (e) {
2         console.log(e.origin,e.data)
3     })

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

后记

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

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

127.0.0.1 1.com
127.0.0.1 2.com

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

参照信息:

HTML5 postMessage 和 onmessage API 详细应用

http://msdn.microsoft.com/en-us/library/ie/cc197015(v=vs.85).aspx

http://stackoverflow.com/questions/16226924/is-cross-origin-postmessage-broken-in-ie10

https://developer.mozilla.org/zh-CN/docs/Web/API/Window.postMessage

本文来自:http://jo2.org/html5-js-postmessage-tips/

时间: 2025-01-18 05:39:31

HTML5的postMessage使用记要的相关文章

html5的postmessage实现js前端跨域访问及调用解决方案

关于跨域访问,使用JSONP的方法,我前面已经demo过了,具体见http://supercharles888.blog.51cto.com/609344/856886,HTML5提供了一个非常强大的API,叫postMessage,它其实就是以前iframe的进化版本,使用起来极其方便,这里举个实验例子: 我们依旧按照与上文相同的设定,假定我们有2个Domain Domain1: http://localhost:8080  它上面有个应用叫HTMLDomain1,并且有个页面叫sender.

使用HTML5中postMessage 实现ajax中的POST跨域问题

HTML5中提供了在网页文档之间相互接收与发送信息的功能.使用这个功能,只要获取到网页所在窗口对象的实例,不仅仅同源(域+端口号)的web网页之间可以互相通信,甚至可以实现跨域通信. 浏览器支持程度:IE8+,firefox4+,chrome8+  opera10+ 1. 首先,要想接收从其他的窗口发过来的消息,就必须对窗口对象的message事件进行监听,如下代码: window.addEventListener(“message”, function(){},false); 2. 其次,需要

HTML5 postMessage 跨域交换数据

前言 之前简单讲解了利用script标签(jsonp)以及iframe标签(window.name.location.hash)来跨域交换数据,今天我们来学习一下HTML5的api,利用postMessage来跨域交换数据.和前面一些方式交换数据方式不同的是,利用postMessage不能和服务端交换数据,只能在两个窗口(iframe)之间交换数据,废话不多说,我们直接进入实战. 实战postMessage overview 上文中说,postMessage是用于两个窗口(iframe)之间交换

html5 postMessage解决跨域、跨窗口消息传递

问题: 对于跨域问题,研究了一下html5的postMessage,写了代码测试了一下,感觉html5新功能就是好用啊. 此文仅使用html5的新特性postMessage,演示其执行过程和效果: 方法解释:postMessage()方法允许来自不同源的脚本采用异步方式进行有限的通信,可以实现跨文本档.多窗口.跨域消息传递.postMessage(data,origin)方法接受两个参数: 1.data:你需要传递的消息,消息传递的格式有一定要求:参数可以是JavaScript的任意基本类型或可

[HTML5_WebWorkers]利用HTML5的window.postMessage实现跨域通信

由于同源策略的限制,JavaScript跨域的问题,一直是一个颇为棘手的问题,为了解决js的跨域,web开发人员是煞费苦心,研究了各种跨域方案,如果有机会的话,明河以后会一一展示给各位,今天明河重点介绍下html5新引入的postMessage跨域方案. 1.哪些场景要考虑跨域问题? 明河这二周在处理淘宝添加收藏夹的重构,里面就有一个非常经典的跨域问题.添加收藏弹出层外层是淘宝商城页面域名是tmall.com,而弹出层内部的页面域名却是taobao.com,接下来的问题就是我现在希望弹出层内部的

跨域(五)——postMessage

HTML5的postMessage机制是客户端最直接的中档传输方法,一般用在iframe中父页与子页之间的客户端跨域通信. 浏览器支持情况:Chrome 2.0+.Internet Explorer 8.0+, Firefox 3.0+, Opera 9.6+, 和 Safari 4.0+ . Facebook已经使用了这个功能,用postMessage支持基于web的实时消息传递. 用法:otherWindow.postMessage(message, targetOrigin) otherW

[HTML5_WebWorkers]HTML5 web通信(跨文档通信/通道通信)简介

一.简单概要 web通信(洋名:web messaging)是一种文档中独立的浏览上下文间的DOM不会被恶意的跨域脚本暴露数据分享方式. 得得得,术语啊什么的,比看到凤姐还头疼.有必要把上面一句话拆开讲: web通信是一种数据分享方式(有屁话之嫌): 通信的主体是“浏览上下文”(这是纳尼?): 哦,“浏览上下文”呢是“一个将 Document对象呈现给用户的环境”,你可以近似理解为平常我们看到的某个页面所处的环境: web通信不会有DOM被恶意暴露的危险: 目前应用比较多的就是iframe之间的

HTML5 Web存储--localStorage/sessionStorage

HTML5提供了2种在客户端存储的方法: 1.localStorage--没有时间限制的数据存储 2.sessionStorage --针对一个session的数据存储,会话结束时会被清空 一.作用域 作用域 localStorage在相同的协议.主机名.端口下,就能读取/修改到同一份localStorage数据 sessionStorage在上述的条件下还要求在同一个窗口,也就是只要关闭了浏览器(包括关闭标签页),就会被清空 二.VS cookie: 1.存储数据更多 ( cookie只有4k

postMessage和sendMessage

参考:http://www.cnblogs.com/giggle/p/5350288.html(浅谈webWorker) http://blog.csdn.net/zha_zi/article/details/41677033 HTML5 中 postMessage sendMessage 用法 Web Workers----工作线程 Html5对多线程的支持.在 HTML5 中提出了工作线程(Web Workers)的概念.用于解决页面之间数据处理的多线程,加快数据处理.如同java中的Thr