跨所有浏览器从 iFrame 传递消息

Posted

技术标签:

【中文标题】跨所有浏览器从 iFrame 传递消息【英文标题】:Passing Messages from iFrame Across all Browsers 【发布时间】:2011-11-20 17:02:42 【问题描述】:

我有一个可嵌入的 iframe,将在 3rd 方网站上使用。它有几个表格要填写,最后必须通知父页面已完成。

换句话说,点击按钮时,iframe 需要向其父级传递消息。

在经历了“不,跨域策略是个混蛋”的海洋之后,我找到了window.postMessage,它是 html5 草案规范的一部分。

基本上,您在页面中放置以下 javascript 以从 iframe 捕获消息:

window.addEventListener('message', goToThing, false);

function goToThing(event) 
    //check the origin, to make sure it comes from a trusted source.
    if(event.origin !== 'http://localhost')
        return;

    //the event.data should be the id, a number.
    //if it is, got to the page, using the id.
    if(!isNaN(event.data))
        window.location.href = 'http://localhost/somepage/' + event.data;

然后在 iframe 中,有一些 JavaScript 向父级发送消息:

$('form').submit(function()
    parent.postMessage(someId, '*');
);

太棒了,对吧?唯一的问题是它似乎不适用于任何版本的 IE。所以,我的问题是:鉴于我需要将消息 一个 iframe 传递给它的父级(我都控制这两个),有没有一种我可以使用的方法可以跨任何 (>IE6) 浏览器?

【问题讨论】:

caniuse.com/#search=postMessage 【参考方案1】:

在 IE 中你应该使用

attachEvent("onmessage", postMessageListener, false);

而不是

addEventListener("message", postMessageListener, false);

【讨论】:

【参考方案2】:

我见过的主要解决方法包括在父窗口上设置哈希值并检测父窗口中的哈希值,解析哈希值以获取数据并做任何你想做的事情。这是一个这样做的例子:http://www.onlineaspect.com/2010/01/15/backwards-compatible-postmessage/。通过 Google 可以提供更多选择,例如:http://easyxdm.net/wp/。

【讨论】:

看起来很有希望;现在试试这个。 在阅读了您的链接后,我最终得到了一个混合解决方案。如果 postMessage 支持浏览器使用它,否则它使用旧的 url-hash 样式和轮询。为了支持后退按钮,我添加了一个额外的步骤,设置 window.location.href = '#!',在找到 url 后立即从 url 中清除哈希值。【参考方案3】:

这比那更简单。

您说您可以同时控制框架的父级和内容,您可以通过两种方式进行设置 javascript中的通信。

你只需要

yourframename.document.getElementById('idofsomethinginttheframe')

然后从框架内部寻址它之外的任何内容

parent.document

【讨论】:

Eeeh...我不喜欢处理 DOM 操作以进行数据传递,如果我能侥幸逃脱的话。我改为使用 URL 哈希方法。 他说的是“第三方网站”,所以由于 SOP,直接访问是不可能的。 @webjunkie 我非常了解 SOP,但您没有完全阅读该帖子。 “然后在 iframe 中,有一些向父级发送消息的 JavaScript”+ 代码。只有当您能够在 iframe 中编辑源时,您才能这样做。因此,无论 OP 在介绍中说什么,都与更改框架内容中的代码的能力不一致。如果您具有该能力,则它不是被陷害的第 3 方站点。如果您因此而投反对票,那么我请您纠正它。 @T9b 在父框架中控制或更改代码的能力与同源的父子框架不同。 @T9b 第三方站点是父站点。自己去好好读吧。这里有有效的 SOP,这就是为什么他甚至开始用 PostMessage 询问。

以上是关于跨所有浏览器从 iFrame 传递消息的主要内容,如果未能解决你的问题,请参考以下文章

PhoneGap 中的 postMessage 不起作用 - iframe 到父消息传递

iframe可通过postMessage解决跨域跨窗口消息传递

将 IFrame 设置为“about:blank”的跨浏览器方式?

解决Iframe跨域高度自适应,利用window.postMessage()实现跨域消息传递页面高度(JavaScript)

Html5 postMessage实现跨域消息传递

访问 <iframe> 元素的窗口和文档的最简洁的跨浏览器方法是啥?