JavaScript的;具有相同来源的标签/窗口之间的通信

时间:2010-02-10 12:49:21

标签: javascript html5 web-applications local-storage postmessage

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

  • 窗口A和窗口B具有相同的域
  • 窗口A和窗口B没有任何父窗口。

问题:

  1. 窗口A是否可以获得窗口B的引用?
  2. 什么是使窗口A通知窗口B的最优雅方式? (包括新的HTML5规范)
  3. 我知道这样做的两种方式:

    • 服务器消息:其中窗口B定期询问服务器窗口A是否已通知
    • 通过本地数据进行消息传递(HTML5):当窗口A想要通知某些内容时,它会更改本地数据,窗口B会定期检查本地数据是否有任何更改。

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

    会很高兴。

    最终的目标是制作类似facebook的内容,如果你打开4个facebook标签并在一个标签中聊天,聊天是最新的每个facebook标签,这很整洁!

6 个答案:

答案 0 :(得分:22)

BroadcastChannel标准允许这样做。现在它已在Firefox和Chrome中实现(caniusemdn):

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

答案 1 :(得分:12)

SharedWorker是WHATWG / HTML5规范,适用于可在标签之间进行通信的常见流程。

答案 2 :(得分:4)

你说你的:

  

utlimate的目标是制作类似facebook的内容,如果你打开4个facebook标签,并在一个标签中聊天,聊天就会在每个facebook标签上实现,这很整洁!

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

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

答案 3 :(得分:4)

除了即将发布的SharedWorker,您还可以使用cross-document messagingsupported更广泛。postMessage。在这种情况下,必须有一个主窗口负责打开window.open的所有其他窗口。然后,子窗口可以在window.opener上使用LocalConnection

如果您使用闪存是一个选项,那么安装了闪存的任何客户端(example code)几乎都支持更旧的postMessage plugin for jQuery with window.location.href fallback for older browsers

其他后备方法:
cookie-based solution for non-instant communication
{{3}}

答案 4 :(得分:1)

AFAIK,如果他们没有相同的父母,则无法通过Windows进行通信。

如果它们都是从父窗口打开的,那么你应该能够掌握父变量引用。

在父母中,打开这样的窗口:

childA = window.open(...);
childB = window.open(...)
在ChildA中,

访问childB,如下所示:

childB = window.opener.childA

答案 5 :(得分:0)

我有一个简洁的方法来做这样的技巧,但有限制:你应该允许你的域弹出窗口,你将得到一个页面总是打开(作为选项卡或弹出窗口),这将实现窗口之间的通信。

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

这个技巧的主要特点 - 弹出窗口正在用url片段'#'打开,这个强制浏览器不会改变窗口位置并存储所有数据。 而window.postMessage完成其余的工作。