在不支持HTML5的浏览器里如何模拟postMessage?

在不支持HTML5的浏览器里如何模拟postMessage实现?

评论 (0)链接2012-03-02 

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

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

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

开源事件库 messageEvent.js

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

接口

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

通过 jQuery 使用它

jQuery 是一个应用比较广泛的 DOM 库,它的事件机制非常强大而精妙。若页面引用了 jQuery, messageEvent.js 会为为它提供支持,你可以用熟悉的jQuery api 风格编程,如:

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

jQuery(window).message(function (event) {
alert(event.data)
});
jQuery.postMessage(iframe.contentWindow, 'hello world', '*');

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

参考来源:跨浏览器 HTML5 postMessage 方法以及 message 事件模拟实现

该答案已被锁定,无法对其进行评论,编辑及投票。
()
评论 (0)链接 • 2012-03-02

如果考虑使用flash的话,可以使用flash的Localconection。
不但可以进行跨文档(可以是不同域下的)通信,甚至还可以跨浏览器间的通信。
但存在问题是:如果消息通信过于频繁,localconection存在消息队列阻塞的情况。

具体的实现不给出了。可以去参考下ActionScript手册。

该答案已被锁定,无法对其进行评论,编辑及投票。
()
评论 (0)链接 • 2012-11-08
德问是一个专业的编程问答社区,请 登录注册 后再提交答案