17

私はこれに何時間も立ち往生しています。

http://subdomain.example.comの b.html への src を持つ iframe を含むhttp://example.comに a.html があります。a.html には、postMessage を iframe に送信するための JS コードが含まれています。

postMessage のコードは単純です。

iframe_window.postMessage('message', iframe_element.src)

しかし、この方法では、Chrome はエラーをスローします。

Unable to post message to http://subdomain.example.com. Recipient has origin null.

私も試しました:

iframe_window.postMessage('message', 'http://subdomain.example.com')

しかし運が悪い!

これが機能する唯一の方法です。

iframe_window.postMessage('message', '*')

しかし、「*」は使いにくいと聞いたことがあります。

Firefox では問題ありません。

4

2 に答える 2

27

これは、シグナルの送信時に子 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 でこれをテストしたところ、このソリューションが機能しました。

于 2012-12-15T02:23:58.073 に答える