Javascript; связь между вкладками / окнами с одинаковым происхождением

У меня есть два окна: окно А и окно Б.

  • окно A и окно B имеют одинаковый домен
  • Окно A и окно B не имеют родительского окна.

Вопросы:

  1. Возможно ли для окна A получить ссылку на окно B?
  2. Каков самый элегантный способ сделать окно A уведомить что-то к окну B?
    (включая новые спецификации HTML5)

Мне известно о двух способах сделать это:

  • обмен сообщениями через сервер: где окно B регулярно запрашивает сервер, уведомило ли окно A что-то
  • обмен сообщениями по локальным данным (HTML5): когда окно A хочет что-то уведомить, оно изменяет локальные данные, окно B регулярно проверяет локальные данные на наличие изменений.

Но два способа не так уж и элегантны.
Например, было бы неплохо получить ссылку на окно B и использовать window.postMessage() (HTML5)

Конечная цель состоит в том, чтобы сделать что-то вроде Facebook, где, если вы откроете 4 вкладки в Facebook и общаетесь в одной вкладке, чат обновляется на каждой вкладке Facebook, что очень удобно!

7 ответов

Решение

Я придерживаюсь общего локального решения данных, упомянутого в вопросе, используя localStorage, Кажется, это лучшее решение с точки зрения надежности, производительности и совместимости с браузерами.

localStorage реализовано во всех современных браузерах.

storage событие запускается, когда другие вкладки вносят изменения в localStorage, Это очень удобно для общения.

Список литературы можно найти здесь:
Веб-хранилище
Webstorage - складское мероприятие

Стандарт BroadcastChannel позволяет сделать это. Прямо сейчас это реализовано в Firefox и Chrome ( caniuse, mdn):

// 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);
});

SharedWorker - это спецификация WHATWG/ HTML5 для общего процесса, который может взаимодействовать между вкладками.

Помимо предстоящего SharedWorker, вы также можете использовать обмен сообщениями между документами, который гораздо более широко поддерживается. В этом сценарии должно быть главное окно, которое отвечает за открытие всех других окон с window.open, Затем дочерние окна могут использовать postMessage на своих window.opener,

Если использование флэш-памяти является опцией для вас, существует также гораздо более старая версия LocalConnection, практически поддерживаемая любым клиентом с установленной флэш-памятью ( пример кода).

Другие альтернативные методы:
плагин postMessage для jQuery с окном window.location.href для старых браузеров
решение на основе файлов cookie для мгновенного общения

Вы сказали свое:

Цель utlimate - сделать что-то вроде Facebook, где, если вы откроете 4 вкладки в Facebook и общаетесь в одной вкладке, чат актуализируется на каждой вкладке Facebook, что очень удобно!

Это должно происходить как побочный продукт вашего дизайна - представления, запрашивающие модель (возможно, сервер) для обновления чата, а не необходимость проектирования в межпросмотровом общении. Если вы не имеете дело с передачей огромных объемов данных, зачем беспокоиться об этом? Кажется, что это усложнит ситуацию без огромного выигрыша.

Несколько лет назад я обнаружил, что если бы я сделал window.open используя имя существующего окна и пустой URL, я получил ссылку на существующее окно (такое поведение даже задокументировано в MDC, а комментарий к документации MSDN предполагает, что оно работает и в IE). Но это было много лет назад, я не знаю, насколько универсальна его поддержка в современном мире, и, конечно, у вас не будет имени окна, которое нужно искать, если все ваши окна не содержат именованные iframe для связи, уникально именуемый через код на стороне сервера, а затем сообщаемый другим окнам с помощью кода на стороне сервера... (Страшная мысль: это может быть реально осуществимо. Сохраните "текущие" имена окон, относящиеся к зарегистрированному в учетной записи в таблице, передайте список любому новому созданному окну, которое входит в эту учетную запись, отбрасывайте старые неактивные записи. Но если список немного устарел, вы будете открывать новые окна при поиске других... И я поддержка ставок сомнительна от браузера к браузеру.)

AFAIK, невозможно общаться через окна, если у них нет одного и того же родителя.

Если они оба были открыты из родительского окна, вы сможете получить ссылки на переменные родителя.

В родительском окне откройте окна следующим образом:

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

в ChildA, доступ к childB, как это:

childB = window.opener.childA

У меня есть отличный способ сделать такой трюк, но с ограничениями: вы должны разрешить всплывающие окна для своего домена, и вы всегда будете получать одну открытую страницу (как вкладку или как всплывающее окно), которая будет осуществлять связь между окнами.

Вот пример: http://test.gwpanel.org/test/page_one.html(обновить страницу после включения всплывающих окон для домена)

Главная особенность этого трюка - открытие всплывающего окна с фрагментом URL '#', что заставляет браузер не менять расположение окна и хранить все данные. И window.postMessage сделает все остальное.

Другие вопросы по тегам