JavaScript的; 相同来源的标签/窗口之间的通信
我有两个窗口:窗口A和窗口B.
- 窗口A和窗口B具有相同的域
- 窗口A和窗口B没有任何父窗口。
问题:
- 窗口A是否有可能获得窗口B的引用?
- 什么是最优雅的方式使窗口A通知窗口B?
(包括新的HTML5规范)
两种方式我知道这样做:
- 通过服务器发送消息:窗口B定期询问服务器,如果窗口A已经通知了某事
- 通过本地数据(HTML5)进行消息传递:当窗口A想要通知某些内容更改本地数据时,窗口B会定期检查本地数据是否有任何更改。
但是这两种方式并不那么优雅。
例如,获得窗口B的引用并使用window.postMessage()(HTML5)
最终的目标是做一些类似facebook的地方,如果你打开4个facebook标签并且在一个标签上聊天,那么在每个facebook标签中聊天都是最新的,这个标签是整洁的!
我坚持使用localStorage
问题中提到的共享本地数据解决scheme。 这似乎是可靠性,性能和浏览器兼容性方面的最佳解决scheme。
localStorage
在所有现代浏览器中实现。
当其他选项卡更改localStorage
时, storage
事件触发。 这对通信目的来说非常方便。
参考可以在这里find:
Webstorage
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规范,用于可以在选项卡之间进行通信的常用过程。
你说过你的:
最大的目标就是制作一些类似于Facebook的东西,如果你打开4个Facebook标签页,并且在一个标签页上聊天,聊天function就会在每个Facebook标签页上实现,而且整洁!
这应该作为你的devise的副产品,查询模型(可能是服务器)更新聊天的意见,而不是你必须devise交叉视图通信。 除非你处理大量的数据传输,为什么要担心呢? 看起来似乎会让事情变得复杂而没有巨大的收益。
几年前,我发现,如果我使用现有窗口的名称和空白URL做了window.open
,我得到了对现有窗口的引用(这种行为甚至logging在MDC上, 对MSDN文档的评论表明它可以工作IE以及)。 但那是几年前,我不知道当今世界对它的支持有多普遍,当然,除非你所有的窗口都包含一个用于通信的命名的iframe
,否则你将不会有窗口名称,唯一命名的通过服务器端代码,然后通过服务器端代码传递给其他窗口…(可怕的想法:这实际上是可行的。将与当前login帐户相关的“当前”窗口名称存储在表中,给列表的任何新窗口创buildlogin到该帐户,剔除旧的非活动条目,但如果列表稍微过时,你会打开新窗口时,search其他人…我敢打赌,支持是如果从浏览器到浏览器。)
除了即将推出的SharedWorker ,您还可以使用跨文档消息传递 ,这得到了更广泛的支持 。 在这种情况下,必须有一个主窗口负责用window.open
打开所有其他窗口。 然后子窗口可以在他们的window.opener
上使用postMessage 。
如果使用闪存是您的一个select,那么在安装了闪存的任何客户端( 示例代码 )上也可以实际支持更旧的LocalConnection 。
其他回退方法:
用于jQuery的postMessage插件,用于旧版浏览器的window.location.href后备
基于cookie的非即时通信解决scheme
AFAIK,如果他们不具有相同的父项,则不可能跨窗口进行通信。
如果它们都是从父窗口打开的,则应该能够获得父项的variables引用。
在父项中,像这样打开窗口:
childA = window.open(...); childB = window.open(...)
在ChildA中,像这样访问childB:
childB = window.opener.childA
我有一个很好的方法来做这样的伎俩,但有一些限制:你应该允许你的域名popup,你会得到一个页面总是打开(如选项卡或popup),将实现窗口之间的通信。
下面是一个例子: http : //test.gwpanel.org/test/page_one.html (在为域启用popup窗口后刷新页面)
这个技巧的主要特点是popup窗口最后是用“#”碎片打开,这个强制浏览器不改变窗口位置并存储所有的数据。 其余的就是window.postMessage。