Javascript; связь между вкладками / окнами с одинаковым происхождением
У меня есть два окна: окно А и окно Б.
- окно A и окно B имеют одинаковый домен
- Окно A и окно B не имеют родительского окна.
Вопросы:
- Возможно ли для окна A получить ссылку на окно B?
- Каков самый элегантный способ сделать окно 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 сделает все остальное.