Javascript;具有相同来源的选项卡/窗口之间的通信

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2236828/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-22 23:24:21  来源:igfitidea点击:

Javascript; communication between tabs/windows with same origin

javascripthtmlweb-applicationslocal-storagepostmessage

提问by brillout

I have two windows: window A and window B.

我有两个窗口:窗口 A 和窗口 B。

  • window A and window B have same domain
  • window A and window B doesn't have any parent window.
  • 窗口 A 和窗口 B 具有相同的域
  • 窗口 A 和窗口 B 没有任何父窗口。

Questions:

问题:

  1. Is it possible for window A to get a reference of window B?
  2. what is the most elegant way to make window A notify something to window B?
    (including new HTML5 specs)
  1. 窗口 A 是否有可能获得窗口 B 的引用?
  2. 让窗口 A 通知窗口 B 的最优雅的方法是什么?
    (包括新的 HTML5 规范)

Two ways i am aware of doing this:

我知道这样做的两种方式:

  • messaging by server: where window B regulary asks the server if window A has notified something
  • messaging by local data (HTML5): when window A wants to notify something it changes the local data, window B regulary checks the local data for any changes.
  • 服务器消息传递:其中窗口 B 定期询问服务器窗口 A 是否已通知某些内容
  • 本地数据消息传递(HTML5):当窗口 A 想要通知某事它更改了本地数据时,窗口 B 会定期检查本地数据是否有任何更改。

But the two ways are not so elegant.
For example it would be nice to get a reference of window B and use window.postMessage() (HTML5)

但是这两种方式都不是那么优雅。
例如,获得窗口 B 的引用并使用 window.postMessage() (HTML5) 会很好

Ultimate goal is to make something like facebook where if you open 4 facebook tabs and chat in one tab, the chat is up to date in every facebook tab, which is neat!

最终目标是制作类似于 facebook 的东西,如果您打开 4 个 facebook 标签并在一个标签中聊天,则每个 facebook 标签中的聊天都是最新的,这很整洁!

回答by brillout

I'm sticking to the shared local data solution mentioned in the question using localStorage. It seems to be the best solution in terms of reliability, performance, and browser compatibility.

我坚持使用问题中提到的共享本地数据解决方案localStorage。它似乎是可靠性、性能和浏览器兼容性方面的最佳解决方案。

localStorageis implemented in all modern browsers.

localStorage在所有现代浏览器中实现。

The storageevent fires when othertabs makes changes to localStorage. This is quite handy for communication purposes.

storage其他选项卡对 进行更改时会触发该事件localStorage。这对于通信目的非常方便。

References can be found here:
Webstorage
Webstorage - storage event

可在此处找到参考:
Webstorage
Webstorage - 存储事件

回答by Joel Richard

The BroadcastChannel standard allows to do this. Right now it is implemented in Firefox and Chrome (caniuse, mdn):

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

回答by rektide

SharedWorker is the WHATWG/ HTML5 spec for a common process that can communicate amongst tabs.

SharedWorker 是 WHATWG/HTML5 规范,用于可以在选项卡之间进行通信的通用进程。

回答by zah

Besides the upcoming SharedWorker, you can also use cross-document messaging, which is much more widely supported. In this scenario, there must a be a main window that is responsible for opening all other windows with window.open. The child windows can then use postMessageon their window.opener.

除了即将推出的SharedWorker 之外,您还可以使用支持更广泛的跨文档消息传递。在这种情况下,必须有一个主窗口负责打开所有其他带有. 然后,子窗口可以使用的postMessage他们。window.openwindow.opener

If using flash is an option for you, there is also the much older LocalConnectionvirtually supported on any client with flash installed (example code).

如果您可以选择使用 flash,那么任何安装了 flash 的客户端实际上都支持更旧的LocalConnection示例代码)。

Other fallbacks methods:
postMessage plugin for jQuery with window.location.href fallback for older browsers
cookie-based solution for non-instant communication

其他回退方法:
用于 jQuery 的 postMessage 插件,带有 window.location.href 回退旧浏览器
基于 cookie 的非即时通信解决方案

回答by T.J. Crowder

You said your:

你说你的:

utlimate goal is to make something like facebook where if you open 4 facebook tabs, and chat in one tab, the chat is actualize on every facebook tab, wich is neat!

最终目标是制作像 facebook 这样的东西,如果你打开 4 个 facebook 标签,并在一个标签中聊天,聊天会在每个 facebook 标签上实现,这很整洁!

That should happen as a by-product of your design, the views querying the model (probably the server) for updates to the chat, rather than your having to design in cross-view communication. Unless you're dealing with transferring huge amounts of data, why worry about it? It seems like it'll complicate things without a huge gain.

这应该作为您设计的副产品发生,视图查询模型(可能是服务器)以更新聊天,而不是您必须在跨视图通信中进行设计。除非您正在处理传输大量数据,否则为什么要担心呢?似乎它会使事情复杂化而没有巨大的收益。

Years ago I found that if I did window.openusing the name of an existing window and a blank URL, I got a reference to the existing window (this behavior is even documented on MDCand a comment on the MSDN docssuggests it works in IE as well). But that was years ago, I don't know how universal the support for it is in today's world, and of course you won't have a window name to look for unless all of your windows include a named iframefor communication, named uniquely via server-side code, and then communicated to the other windows by means of server-side code... (Scary thought: That might actually be feasible. Store the "current" window names related to a logged-in account in a table, give the list to any new window created that logs into that account, cull old inactive entries. But if the list is slightly out of date, you'll open new windows when searching for others... And I bet support is iffy from browser to browser.)

几年前,我发现如果我确实window.open使用了现有窗口的名称和空白 URL,我会得到对现有窗口的引用(这种行为甚至记录在 MDC,MSDN 文档评论表明它也适用于 IE )。但那是几年前的事了,我不知道当今世界对它的支持有多普遍,当然除非您的所有窗口都包含一个已命名的窗口,否则您将无法查找窗口名称iframe用于通信,通过服务器端代码唯一命名,然后通过服务器端代码与其他窗口通信......(可怕的想法:这可能实际上是可行的。存储与记录相关的“当前”窗口名称-在表中的帐户中,将列表提供给登录该帐户的任何创建的新窗口,剔除旧的非活动条目。但如果列表稍微过时,您将在搜索其他人时打开新窗口......我下注支持从浏览器到浏览器都是不确定的。)

回答by Pekka

AFAIK, it is impossible to communicate across windows if they do not have the same parent.

AFAIK,如果它们没有相同的父级,则无法跨窗口进行通信。

If they have both been opened from a parent window, you should be able to get hold of the parent's variable references.

如果它们都从父窗口打开,您应该能够获得父窗口的变量引用。

In the parent, open the windows like this:

在父级中,像这样打开窗口:

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

in ChildA, access childB like this:

在 ChildA 中,像这样访问 childB:

childB = window.opener.childA

回答by Riki_tiki_tavi

I have a neat way to do such trick, but with restrictions: you should allow popups for your domain and you will get one page always opened (as tab or as popup) which will implement communications between windows.

我有一个巧妙的方法来做这样的把戏,但有限制:你应该允许你的域弹出窗口,并且你将始终打开一个页面(作为选项卡或弹出窗口),这将实现窗口之间的通信。

Here's an example: http://test.gwpanel.org/test/page_one.html(refresh page after enabling popups for domain)

这是一个示例:http: //test.gwpanel.org/test/page_one.html(为域启用弹出窗口后刷新页面)

The main feature of this trick - popup is being opened with url fragment '#' in the end, this force browser to don't change window location and store all the data. And window.postMessage do the rest.

这个技巧的主要特点 - 弹出窗口最后以 url 片段“#”打开,这迫使浏览器不要更改窗口位置并存储所有数据。剩下的就交给 window.postMessage 吧。