postMessageを用いたiframeのクロスドメイン通信問題の詳細な解決法
今週は頭の痛いことに遭遇しました。別のサードパーティのウェブプロジェクトを私のウェブプロジェクトに組み込みたかったのです。最初に思いついたのはiframeを使うことでしたが、問題はサードパーティのウェブプロジェクトとやりとりすることで、同一生成元ポリシーに違反すること、そしてクロスドメインの問題に対処することが最大の頭痛の種でした。
要件は、私のページでいくつかのボタンをクリックし、リアルタイムでiframeのサブページにフィードバックし、サブページが応答することです。
最初に思い浮かんだ解決策は、NGINXを使用して、同じドメイン下にある2つのプロジェクトをプロキシすることでした。しかし、それは少し些細なことのように思えます。
windowオブジェクトの下に、クロスドメイン通信の問題を解決するために特別に設計されたpostMessageメソッドがあります。
について ポストメッセージ 以下、postMessageを使ってiframeのクロスドメイン通信を実現する方法を見ていきますが、実際に使ってみてからドキュメントに戻ると、感覚が全く違いますね。
まず、2つの異なるソースからの2つのページがあり、iframePage.html が index.html のサブページであると仮定して、シナリオをシミュレートしてみましょう。
<! -- index.html -->
<body style="border:5px solid #333;">
<h1>this is index</h1>
<iframe src=". /iframePage.html" id='myframe'></iframe>
</body>
<! -- iframePage -->
<body style="border:5px solid #333;">
<h1>this is iframePage</h1>
</body>
さて、2つのiframeはソースが異なるため通信できず(クロスドメインの問題があるとして)、そこでpostMessageの出番となるわけです。
親ページから子ページへメッセージを送ってみましょう。
// idnex.html
// Get the iframe element
iFrame = document.getElementById('myframe')
// Send the message after the iframe is loaded, otherwise the subpage will not receive the message
iFrame.onload = function(){
//Send a message immediately after the iframe is loaded
iFrame.contentWindow.postMessage('MessageFromIndex1','*');
}
postMessageはwindowオブジェクトに搭載されていることが分かっているので、iframeが読み込まれたらiFrame.contentWindowを使ってiframeのwindowオブジェクトを取得し、postMessageメソッドを呼び出せば、サブページにメッセージを送ったのと同じ意味になります。
postMessageメソッドの第一引数は、送信するデータで、任意の生の型が使用可能です。
Gecko 6.0 (Firefox 6.0 / Thunderbird 6.0 / SeaMonkey 2.3) より前のバージョンでは、最初のパラメータは文字列でなければなりません。
postMessageメソッドの第2パラメータは、送信先のURLを設定します。現在のサブページのurlが設定されたものと一致しない場合、送信に失敗するので、これを*に設定し、すべてのurlの送信を許可するようにします。
postMessageメソッドには第3パラメータがありますが、これは高度な使い方で、ここでは説明しませんので、後でMDNで勉強してください。
iframePage.htmlにメッセージが送信され、メッセージを受信することができます。
// iframePage.html
// callback function
function receiveMessageFromIndex ( event ) {
console.log( 'receiveMessageFromIndex', event )
}
//Listen to the message event
window.addEventListener("message", receiveMessageFromIndex, false);
あとは、サブページのメッセージイベントをリスニングして、イベントがプリントアウトされるのを見るためにコールバック関数をセットアップするだけです。
イベントオブジェクトのdataプロパティには、親ページから渡されたデータが格納されています。
もう一度、子ページから親ページへのデータ送信を試してみましょう。
// iframePage.html
// send a message to the parent page, with data as the object
parent.postMessage( {msg: 'MessageFromIframePage'}, '*');
親ページがデータを受信します。
//index.html
// callback function
function receiveMessageFromIframePage (event) {
console.log('receiveMessageFromIframePage', event)
}
//Listen to the message event
window.addEventListener("message", receiveMessageFromIframePage, false);
なるほど、確かに異なるデータを送信することは可能ですね、この時点でデータはのオブジェクトです。
人々は、以下の場所に行くことができます。 ポストメッセージデモ をクリックすると、コードをクローンして試せます。
以上、本記事が皆様の学習のお役に立てれば幸いです。また、スクリプトハウスを応援していただければ幸いです。
関連
-
キャンバスを使った雪の結晶の効果を実現するコード例
-
AmazeUIがモーダルボックスにフォームを埋め込んでモーダルインプットボックスを形成する
-
iosシステムでhtml5のvideoタグが再生できない問題を解決する。
-
Html5ナビゲーションバー天井画の原理と対照的な実装
-
H5 オフラインストレージ マニフェストの原理と使い方
-
html2canvasのスクリーンショットが空白になる問題の解決法
-
円形のプログレスバーを生成する html svg
-
IOSキーボードがfocusoutイベントでしまわれたときに元の場所に戻らない問題を解決する
-
html2canvas.jsを使用してページのスクリーンショットを撮影し、表示またはアップロードするサンプルコード
-
モバイルhtml5で長押しイベントをシミュレートする方法
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
html5で複数ページ通信を行うsharedWorkerのコード例
-
キャンバスは、マウスがまぶしい小さなボールの実装に従ってください。
-
CAPTCHAを生成するHTML5サンプルコード
-
Html5 Streamを用いたリアルタイムモニタリングシステムの開発
-
localStorageの最大記憶容量を取得する方法を説明する
-
9ボックスグリッドの原則を用いたHTMLページレイアウト
-
html5 自動再生 mov形式動画サンプルコード
-
人気のあるいくつかのHTML5 UIフレームワークの比較(要約)
-
QRコードポスター付きキャンバス生成の落とし穴記録
-
localStorageの有効期限を設定する詳細な方法