82

ウィンドウAとウィンドウBの2つのウィンドウがあります。

  • ウィンドウ A とウィンドウ B は同じドメインを持っています
  • ウィンドウ A とウィンドウ B には親ウィンドウがありません。
  1. ウィンドウAがウィンドウBの参照を取得することは可能ですか?
  2. ウィンドウAにウィンドウBに何かを通知させる最もエレガントな方法は何ですか? (新しい HTML5 仕様を含む)

私がこれを行うことを認識している2つの方法:

  • サーバーによるメッセージング: ウィンドウ B は、ウィンドウ A が何か通知したかどうかをサーバーに定期的に尋ねます。
  • ローカル データによるメッセージング (HTML5): ウィンドウ A がローカル データを変更したことを通知したい場合、ウィンドウ B は定期的にローカル データの変更をチェックします。

しかし、2 つの方法はそれほどエレガントではありません。

例えば、window B の参照を取得して window.postMessage() (HTML5) を使うと良いでしょう。

最終的な目標は、4 つの Facebook タブを開いて 1 つのタブでチャットすると、Facebook のすべてのタブでチャットが最新の状態になる Facebook のようなものを作ることです。

4

7 に答える 7

131

を使用した質問で言及されている共有ローカルデータソリューションに固執していlocalStorageます。信頼性、パフォーマンス、ブラウザの互換性の点で最適なソリューションのようです。

localStorage最新のすべてのブラウザに実装されています。

storageイベントは、他のタブがに変更を加えたときに発生しますlocalStorage。これは、コミュニケーションの目的で非常に便利です。

参照はここで見つけることができます:
Webstorage
Webstorage-storage event

于 2012-09-20T14:05:47.837 に答える
30

BroadcastChannel 標準では、これを行うことができます。現在、Firefox と Chrome に実装されています ( caniusemdn ):

// tab 1
var ch = new BroadcastChannel('test');
ch.postMessage('some data');

// tab 2
var ch = new BroadcastChannel('test');
ch.addEventListener('message', function (e) {
    console.log('Message:', e.data);
});
于 2015-05-14T14:54:17.680 に答える
13

SharedWorker は、タブ間で通信できる共通プロセスの WHATWG/ HTML5 仕様です。

于 2010-04-23T23:11:04.753 に答える
4

今後のSharedWorkerに加えて、クロスドキュメント メッセージングも使用できます。これは、より広くサポートされています。このシナリオでは、他のすべてのウィンドウを で開くメイン ウィンドウが必要window.openです。子ウィンドウは、その後でpostMessageを使用できwindow.openerます。

フラッシュを使用するオプションがある場合は、フラッシュがインストールされているクライアントで仮想的にサポートされているはるかに古いLocalConnectionもあります (サンプル コード)。

その他のフォールバック方法:
window.location.href を使用した jQuery 用の postMessage プラグイン 古いブラウザー用のフォールバック
非即時通信用の Cookie ベースのソリューション

于 2012-09-11T10:44:51.900 に答える
4

あなたはあなたのことを言った:

究極の目標は、4 つの Facebook タブを開いて 1 つのタブでチャットすると、すべての Facebook タブでチャットが実現する Facebook のようなものを作成することです。

これは、クロスビュー通信で設計する必要があるのではなく、ビューがチャットの更新のためにモデル (おそらくサーバー) にクエリを実行する設計の副産物として発生するはずです。膨大な量のデータを転送する場合を除き、心配する必要はありません。大きな利益を得ることなく物事を複雑にするようです。

window.open何年も前に、既存のウィンドウの名前と空白の URL を使用すると、既存のウィンドウへの参照が得られることがわかりました(この動作はMDN でも文書化されており、MSDN ドキュメントのコメントは、IE でも機能することを示唆しています。 ; とは言うものの、2017 年に誰かが MDN の記事にいくつかの制限を列挙したやや乱暴なメモを追加しました — 私はそれらを独自に検証していません)。しかし、それは何年も前のことであり、今日の世界でそれがどの程度普遍的にサポートされているかはわかりません。もちろん、すべてのウィンドウに名前付きの名前が含まれていない限り、検索するウィンドウ名はありません。iframe通信のために、サーバー側のコードを介して一意に名前を付け、サーバー側のコードを介して他のウィンドウに通信します... (恐ろしい考え: それは実際に実行可能かもしれません.テーブルのアカウントで、そのアカウントにログインするために作成された新しいウィンドウにリストを与え、古い非アクティブなエントリを選別します.しかし、リストが少し古くなっている場合は、他の人を検索するときに新しいウィンドウを開くでしょう...そして私はベットのサポートはブラウザーごとに異なります。)

于 2010-02-10T13:08:43.663 に答える
1

私の知る限り、同じ親がいない場合、ウィンドウ間で通信することは不可能です。

両方が親ウィンドウから開かれている場合、親の変数参照を取得できるはずです。

親で、次のようにウィンドウを開きます。

childA = window.open(...);
childB = window.open(...)

ChildA では、次のように childB にアクセスします。

childB = window.opener.childA
于 2010-02-10T12:52:15.193 に答える
0

私はそのようなトリックを行う巧妙な方法を持っていますが、制限があります: ドメインのポップアップを許可する必要があり、ウィンドウ間の通信を実装する (タブまたはポップアップとして) 1 つのページが常に開かれます。

例を次に示します: http://test.gwpanel.org/test/page_one.html (ドメインのポップアップを有効にした後にページを更新します)

このトリックの主な特徴 - 最後に URL フラグメント '#' を使用してポップアップが開かれます。これにより、ブラウザーはウィンドウの場所を変更せず、すべてのデータを保存するように強制されます。そして window.postMessage が残りを行います。

于 2010-03-27T19:50:22.740 に答える