跨浏览器 HTML5 postMessage 方法以及 message 事件模拟实现

postMessage 是 HTML5 新方法,它可以实现跨域窗口之间通讯。到目前为止,只有 IE8+, Firefox 3, Opera 9, Chrome 3和 Safari 4 支持,而本篇文章主要讲述 postMessage 方法与 message 事件跨浏览器实现。

postMessage 方法 JSONP 技术不一样,前者是前端擅长跨域文档数据即时通讯,后者擅长针对跨域服务端数据通讯,postMessage 应用场景能说明这个区别:

应用场景举例

  1. webOS 使用 iframe 嵌入第三方应用,此时 webOS 与应用需要实时接收/发送各自的消息与响应事件。
  2. 页面弹出一个由 iframe 层,嵌入第三方提供的图片上传页面,文件上传完毕后需要获取返回图片地址插入到编辑器。
  3. iframe 跨域高度自适应。精心开发5年的UI前端框架!

HTML5 postMessage 方法

postMessage 可以实现跨域文档的消息传输(Cross Document Messaging)。

向外界窗口发送消息:

otherWindow.postMessage(message, targetOrigin);

otherWindow: 指目标窗口,是
window.frames 属性的成员或者由 window.open 方法创建的窗口

参数说明:

  • message:是要发送的消息,类型为
    String、Object (IE8、9 不支持)
  • targetOrigin:是限定消息接收范围,不限制请使用
    ‘*’

HTML5 message 事件

绑定消息事件:

window.addEventListener('message', receiver, false);
function receiver (event) {
  if (event.origin === 'http://example.com') {
    if (event.data === 'Hello world') {
      event.source.postMessage('Hello', event.origin);
    } else {
      alert(event.data);
    };
  };
};

调函数第一个参数接收 Event 对象,有三个常用属性:

message 事件在低版本浏览器下模拟实现

对于支持 postMessage 方法的浏览器直接使用它;而对于 IE6、7 采用了比较成熟的 window.name 保存数据以及跨域 iframe 静态代理动态传输方案,下面简称 Cross Frame。

Cross
Frame

假设在域 www.a.com 上有页面 a.html 和代理页面 proxy-a.html , 另一个域 www.b.com 上有个页面 b.html 和代理页面 proxy-b.html,a.html 需要向 b.html 中发送消息时,页面会创建一个隐藏的 iframe 指向 proxy-b.html ,并把消息赋予 iframe.name 属性,此时 proxy-b.html 可以通过 window.name 获取到消息,由于 proxy-b.html 与 b.html 是同域,proxy-b.html
可以把消息赋予 b.html。 b.html 要给 a.html 发送消息时,原理一样。

自动捕获代理
URL

在 Cross Frame 方案中,通信双方必须确切的知道静态代理文件的 URL,显然这个极大的限制了应用范围,我们可以通过一些约定改善:静态代理文件必须置于通信页面所在域根目录,且文件名必须保持一致,如 messageEvent-proxy.html。

有了上述约定,接下来可以用一些巧妙的方法让双方自动捕获代理 URL。以 http://www.a.com/a.html 通过 iframe 嵌入 http://www.b.com/b.html 保持数据交换为例进行说明:

b.html 的静态代理路径可以通过正则分析 iframe.src 后得知;而从框架 b.html 内获取父页面就比较麻烦了,因为跨域后的 parent.location.href 属性只可写入不可读取,不过还可以借用 document.referrer 属性来分析来路地址得知父页面 url。document.referrer 是一个不稳定的属性,我们可以利用 iframe 中 window.name 刷新也不会变化的特性,用此来保存父页面 a.html 的地址。

持续跟踪
URL
精心开发5年的UI前端框架!

a.html 第一次通过提取 iframe.src 路径可得知 b.html 的地址,假若 b.html 跳转到其他域名的时候,此时就会失去对 iframe 内静态代理的联络。 好在新页面由于能够获取父页面 a.html 保存在 window.name 的静态代理,所以我们可以在新页面初始化的时候向 a.html 传递消息告诉它新的地址,这样就能持续跟踪 iframe 中的 URL。

开源事件库 messageEvent.js

“messageEvent.js”是针对上述方案封装的 message 事件与 postMessage 方法库,它让各个浏览器之间 message 的 Event 对象成员属性统一,event.data 属性能传递多达 2MB 的文本信息,并且能让 IE6-9 浏览器像其他现代浏览一样支持 Object 类型数据进行传递 (内部使用深拷贝方式)。

若应用双方页面都采用 messageEvent.js,即可轻松实现跨域通信。

接口

  • add(callback)添加
    message 事件
  • remove(callback)卸载
    message 事件
  • postMessage(otherWindow,
    message, targetOrigin)向外部窗口发送消息

通过
jQuery 使用它

jQuery 是一个应用比较广泛的 DOM 库,它的事件机制非常强大而精妙,可以实现自定义事件。若页面引用了 jQuery, messageEvent.js 会为为它提供支持,你可以用熟悉的jQuery api 风格编程,如: 精心开发5年的UI前端框架!

jQuery(window).bind('message', function (event) {
      alert(event.data)
}); 

jQuery(window).message(function (event) {
      alert(event.data)
}); 

jQuery.postMessage(iframe.contentWindow, 'hello world', '*'); 

jQuery(window).unbind('message');

由于 jQuery 把包装后的 Event 对象用 data 属性来保存 bind 方法传入的额外数据,导致与 message 事件自身的 event.data 属性冲突——这是一个设计错误。为了让 message 事件能够正确获取 event.data,messageEvent.js 通过操作 jQuery 底层缓存强制覆盖了 bind 方法传入的附加数据 (只针对 message 类型)。当然,我仍然期待 jQuery 未来版本能够取消掉 bind 方法的鸡肋特性。

时间: 2024-10-10 07:52:22

跨浏览器 HTML5 postMessage 方法以及 message 事件模拟实现的相关文章

实现跨浏览器html5表单验证

div:nth-of-type(odd){ float: left; clear: left; } .origin-effect > div:nth-of-type(even){ float: right; clear: right; } .clearfix:after{ content: ""; display:block; clear: both; } .figcaption{ clear: both; color: #999; padding-top: 10px; text

JavaScript跨浏览器绑定事件函数的优化

转载自:http://www.cnblogs.com/yugege/p/5169998.html JavaScript作为一门基于事件驱动的语言(特别是用在DOM操作的时候),我们常常需要为DOM绑定各种各样的事件.然而,由于低版本的IE的不给力,在绑定事件和移除事件监听上都与众不同,我们常常需要自己封装一个跨浏览器绑定(移除)事件的函数.跨浏览器添加(移除)DOM事件的一种非常经典的实现代码如下: //跨浏览器添加事件 function addHandler(target, eventType

跨浏览器事件对象封装

封装一个能够隔离浏览器差异的JavaScript库EventUtil,主要是使用能力检测. var EventUtil={ addHandler:function(element,type,handler){ if(element.addEventListener){ element.addEventListener(type,handler,false); }else if(element.attachEvent){ element.attachEvent('on'+type,handler)

javascript跨域请求解决方法总结

javascript中有同源策略,javascript存在跨域通信的问题.典型例子如:Ajax无法直接请求跨域的普通文件,存在跨域无权限访问的问题. 几种常见的解决方法: JSONP  2.HTML5 postMessage 方法  3.document.domain + iframe  4.iframe+location.hash 一.JSONP web页面上只有<script><img><iframe>这些拥有"src"属性的标签是拥有跨域能力的

js 让浏览器全屏模式的方法launchFullscreen

浏览器全屏模式的启动函数requestFullscreen仍然需要附带各浏览器的js方言前缀 // 判断各种浏览器,找到正确的方法 function launchFullscreen(element) { if(element.requestFullscreen) { element.requestFullscreen(); } else if(element.mozRequestFullScreen) { element.mozRequestFullScreen(); } else if(el

跨浏览器的事件对象-------EventUtil 中的方法及用法

什么是EventUti----封装好的事件对象 在JavaScript中,DOM0级.DOM2级与旧版本IE(8-)为对象添加事件的方法不同 为了以跨浏览器的方式处理事件,需要编写一段“通用代码”,即跨浏览器的事件处理程序 习惯上,这个方法属于一个名为EventUtil的对象 编写并使用该对象后,可保证处理事件的代码能在大多数浏览器下一致的运行 var EventUtil={ addHandler:function(element,type,handler){ //添加事件 if(element

js实现一些跨浏览器的事件方法

用JavaScript实现事件的绑定,移除,以及一些常用的事件属性的获取,时常要考虑到在不同浏览器下的兼容性,下面给出了一个跨浏览器的事件对象: var EventUtil = { on: function(element, type, handler) {/* 添加事件 */ if (element.addEventListener) { element.addEventListener(type, handler, false); } else if (element.attachEvent

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

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

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

仅做学习使用,原文链接:http://www.cnblogs.com/dolphinX/p/3464056.html 一些麻烦事儿 平时做web开发的时候关于消息传递,除了客户端与服务器传值还有几个经常会遇到的问题 1.页面和其打开的新窗口的数据传递 2.多窗口之间消息传递 3.页面与嵌套的iframe消息传递 4.上面三个问题的跨域数据传递 postMessage() 这些问题都有一些解决办法,但html5引入的message的API可以更方便.有效.安全的解决这些难题.postMessage