看起来这可能是发送信号时未加载子 iframe 的问题,因此 iframe.src 没有正确的值。
我做了一些测试,得到了和你一样的错误,但是当我将 postMessage 调用包装在 setTimeout 中并等待 100 毫秒时,没有错误,这告诉我这是一个初始化竞争条件。
以下是我如何在没有 setTimeout 的情况下实现更清洁的解决方案:
家长:
window.addEventListener("DOMContentLoaded", function() {
var iframe = document.querySelector("iframe")
, _window = iframe.contentWindow
window.addEventListener("message", function(e) {
// wait for child to signal that it's loaded.
if ( e.data === "loaded" && e.origin === iframe.src.split("/").splice(0, 3).join("/")) {
// send the child a message.
_window.postMessage("Test", iframe.src)
}
})
}, false)
孩子:
window.addEventListener("DOMContentLoaded", function() {
// signal the parent that we're loaded.
window.parent.postMessage("loaded", "*")
// listen for messages from the parent.
window.addEventListener("message", function(e) {
var message = document.createElement("h1")
message.innerHTML = e.data
document.body.appendChild(message)
}, false)
}, false)
这是一个简单的解决方案,其中孩子将向任何人发出它已加载的信号(使用“*”,这没关系,因为没有发送任何敏感内容。)父母侦听加载的事件并检查它是否是孩子感兴趣在那发射它。
然后父母向孩子发送一条消息,孩子准备好接收它。当孩子收到消息时,它会将数据放入 <h1> 并将其附加到 <body>。
我在 Chrome 中使用实际子域对此进行了测试,该解决方案对我有用。