Javascript; связь между вкладками/окнами с одним и тем же источником
У меня есть два окна: окно A и окно B.
- Окно A и окно B имеют один и тот же домен
- Окно A и окно B не имеют родительского окна.
Вопросы:
- Возможно ли, чтобы окно A получило ссылку на окно B?
- что является самым элегантным способом сделать окно. Что-то сообщить окну B?
(включая новые спецификации HTML5)
Двумя способами я знаю об этом:
- обмен сообщениями по серверу: где окно B регулярно запрашивает сервер, если окно A уведомило что-то
- обмен сообщениями по локальным данным (HTML5): когда окно A хочет уведомить что-то, оно изменяет локальные данные, окно B регулярно проверяет локальные данные на предмет любых изменений.
Но два способа не настолько элегантны.
Например, было бы неплохо получить ссылку на окно B и использовать window.postMessage() (HTML5)
Конечная цель - сделать что-то вроде facebook, где, если вы открываете 4 вкладки facebook и чат на одной вкладке, чат обновляется на каждой вкладке facebook, которая является аккуратной!
Ответы
Ответ 1
Я придерживаюсь общего решения локальных данных, упомянутого в вопросе, используя localStorage
. Это лучшее решение с точки зрения надежности, производительности и совместимости с браузером.
localStorage
реализован во всех современных браузерах.
Событие storage
срабатывает, когда другие вкладки вносят изменения в localStorage
. Это очень удобно для коммуникационных целей.
Ссылки можно найти здесь:
Webstorage
Webstorage - событие хранения
Ответ 2
Стандарт 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);
});
Ответ 3
SharedWorker - спецификация WHATWG/HTML5 для общего процесса, который может связываться между вкладками.
Ответ 4
Ты сказал:
utlimate цель - сделать что-то вроде facebook, где, если вы откроете 4 вкладки facebook и пообщаетесь на одной вкладке, чат актуализируется на каждой вкладке facebook, которая аккуратно!
Это должно происходить как побочный продукт вашего проекта, представления, запрашивающие модель (возможно, сервер) для обновления чата, а не для того, чтобы вы могли проектировать в режиме перекрестного просмотра. Если вы не имеете дело с передачей огромного количества данных, зачем беспокоиться об этом? Похоже, что это усложнит ситуацию без огромного выигрыша.
Несколько лет назад я обнаружил, что если бы я сделал window.open
, используя имя существующего окна и пустой URL, я получил ссылку на существующее окно (это поведение даже документально подтвержден MDC и комментарий документы MSDN предполагает, что он работает и в IE). Но это было много лет назад, я не знаю, насколько универсальна поддержка этого в современном мире, и, конечно же, у вас не будет окна, которое нужно искать, если все ваши окна не включают в себя имя iframe
для связи, однозначно с помощью кода на стороне сервера, а затем передается другим окнам с помощью кода на стороне сервера... (Страшная мысль: это действительно возможно. Храните "текущие" имена окон, связанные с зарегистрированной учетной записью в таблицу, приведите список в любое новое окно, созданное для входа в эту учетную запись, отбросьте старые неактивные записи. Но если список немного устарел, вы откроете новые окна при поиске других... И я уверен, что поддержка iffy от браузера к браузеру.)
Ответ 5
Помимо предстоящего SharedWorker, вы также можете использовать междометия обмена сообщениями, которая гораздо шире поддерживается. В этом случае должно быть главное окно, которое отвечает за открытие всех остальных окон с помощью window.open
. Затем дочерние окна могут использовать postMessage на своих window.opener
.
Если вы используете флэш-память, есть еще более старый LocalConnection, практически поддерживаемый на любом клиенте с установленной вспышкой (пример кода).
Другие методы резервного копирования:
плагин postMessage для jQuery с window.location.href для старых браузеров
решение на основе cookie для немедленной связи
Ответ 6
AFAIK, невозможно общаться через окна, если они не имеют одного и того же родителя.
Если они были открыты из родительского окна, вы должны иметь возможность получить ссылки на родительские переменные.
В родительском окне откройте окна следующим образом:
childA = window.open(...);
childB = window.open(...)
в ChildA, выберите childB следующим образом:
childB = window.opener.childA
Ответ 7
У меня есть аккуратный способ сделать такой трюк, но с ограничениями: вы должны разрешить всплывающие окна для своего домена, и вы получите одну страницу, всегда открытую (как вкладку или всплывающее окно), которая будет осуществлять связь между окнами.
Вот пример:
http://test.gwpanel.org/test/page_one.html
(обновить страницу после включения всплывающих окон для домена)
Основная особенность этого трюка - всплывающее окно открывается с фрагментом url '#', в конце этого браузера с синтаксисом не меняет местоположение окна и сохраняет все данные.
И window.postMessage делают все остальное.