20

我在这方面已经坚持了几个小时了。

我打开了.htmlhttp://example.com包含一个iframe,src为b.html打开http://subdomain.example.com.a.html有一些JS代码将消息发布到iframe。

postMessage的代码很简单:

iframe_window.postMessage(“消息”,iframe_element.src)

但这样,Chrome抛出了一个错误:

无法将消息发布到http://subdomain.example.com。收件人的来源为空。

我还尝试过:

iframe_window.postMessage(“消息”,'http://subdomain.example.com')

但没有好运!

这是唯一可行的方法:

iframe_window.postMessage(“消息”,“*”)

但我听说“*”不好用。

Firefox没有问题。

1
  • 只是为了澄清一下,在你的实际代码中,你使用的是真实的网站吗? 评论 2012年12月11日21:38

2个答案2

重置为默认值
33

看起来这可能是子iframe在发送信号时没有加载的问题,因此iframe.src没有正确的值。

我做了一些测试,得到了与您相同的错误,但当我在setTimeout中封装postMessage调用并等待100毫秒时,没有出现错误,这告诉我这是一个初始化竞争条件。

下面是我如何在没有setTimeout的情况下实现更干净的解决方案:

起源:

window.addEventListener(“DOMContentLoaded”,函数(){var iframe=document.querySelector(“iframe”),_window=iframe.contentWindowwindow.addEventListener(“消息”,函数(e){//等待孩子发出信号,表示它已加载。if(e.data===“loaded”&&e.origin===iframe.src.split(“/”).splice(0,3).join(“/“)){//给孩子发个信息。_window.postMessage(“测试”,iframe.src)}})},错误)

儿童:

window.addEventListener(“DOMContentLoaded”,函数(){//向家长发出信号,告诉他们我们已经上船了。window.parent.postMessage(“已加载”,“*”)//监听来自家长的消息。window.addEventListener(“消息”,函数(e){var消息=document.createElement(“h1”)message.inerHTML=e.datadocument.body.appendChild(消息)},错误)},错误)

这是一个简单的解决方案,在这个解决方案中,子级将向任何人发出其已加载的信号(使用“*”,这没关系,因为没有发送任何敏感信息。)父级侦听已加载的事件,并检查它感兴趣的是发出该事件的子级。

然后父节点向子节点发送一条消息,子节点准备接收消息。当子节点收到消息时,它将数据放入<h1>并将其附加到<body>。

我在Chrome中用实际子域测试了这一点,这个解决方案对我很有效。

2
  • 1
    第一句话看起来这可能是子iframe在发送信号时未加载的问题是我让iframe通信正常工作所需要的线索。。。谢谢! 评论 2016年12月3日23:12
  • 你知道“准备好”的实际条件是什么吗?我认为您不必一直等到DOMContentLoaded,但在iframe开始加载时添加侦听器也为时过早。 评论 2020年9月21日18:25
1

一个较短的解决方案是将postMessage包装在iframe_element.onload函数中。

你的答案

单击“发布您的答案”,表示您同意我们的服务条款并确认您已阅读我们的隐私政策.

不是你想要的答案吗?浏览标记的其他问题问你自己的问题.