看起来这可能是子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中用实际子域测试了这一点,这个解决方案对我很有效。