当前位置: 首页 > 知识库问答 >
问题:

选项卡或窗口之间的通信

万开畅
2023-03-14

我正在寻找一种方法,如何在浏览器中的多个选项卡或窗口之间进行通信(在同一个域上,而不是CORS上)而不留下痕迹。有几种解决办法:

  1. 使用窗口对象
  2. 邮件后传
  3. Cookies
  4. 本地存储

第一种可能是最糟糕的解决方案--你需要从你当前的窗口打开一个窗口,然后你只能在保持窗口打开的情况下进行交流。如果您在任何窗口中重新加载该页,则很可能会丢失通信。

第二种方法,使用postMessage,可能可以实现跨源通信,但会遇到与第一种方法相同的问题。您需要维护一个窗口对象。

第三种方法,使用cookies,在浏览器中存储一些数据,这可以有效地看起来像是向同一域上的所有窗口发送一条消息,但问题是,在清理之前,您永远无法知道所有选项卡是否已经读取了“消息”。您必须实现某种超时以定期读取cookie。此外,您还受到最大cookie长度的限制,最大cookie长度为4KB。

第四个解决方案,使用本地存储,似乎克服了cookie的限制,甚至可以使用事件监听。如何使用在被接受的答案中进行了描述。

编辑2018:公认的答案依然管用,但现代浏览器有一个更新的解决方案,使用BroadcastChannel。请参阅另一个答案以获得一个简单的示例,该示例描述了如何使用BroadcastChannel轻松地在选项卡之间传输消息。

共有2个答案

鲁昕
2023-03-14

有一个专门用于此目的的现代API--广播频道

它很简单,就像:

var bc = new BroadcastChannel('test_channel');

bc.postMessage('This is a test message.'); /* send */

bc.onmessage = function (ev) { console.log(ev); } /* receive */

消息不需要仅仅是一个DOMString,任何类型的对象都可以发送。

也许,除了API的清洁性之外,它是这个API的主要优点--没有对象stringization。

目前只支持Chrome和Firefox,但你可以找到一个使用本地存储的polyfill。

萧鹏云
2023-03-14

编辑2018:你可能会更好地使用BroadcastChannel,参见下面的其他答案。但是,如果您仍然喜欢使用localstorage来进行选项卡之间的通信,请使用以下方法:

为了在一个选项卡向其他选项卡发送消息时得到通知,您只需绑定“storage”事件。在所有选项卡中,执行以下操作:

$(window).on('storage', message_receive);

每次在任何其他选项卡中设置localStorage的任何值时,都会调用message_receive函数。事件侦听器还包含新设置为localStorage的数据,因此您甚至不需要解析localStorage对象本身。这是非常方便的,因为您可以在设置值后刚好重置它,以有效地清除任何跟踪。以下是用于消息传递的函数:

// use local storage for messaging. Set message in local storage and clear it right away
// This is a safe way how to communicate with other tabs while not leaving any traces
//
function message_broadcast(message)
{
    localStorage.setItem('message',JSON.stringify(message));
    localStorage.removeItem('message');
}


// receive message
//
function message_receive(ev)
{
    if (ev.originalEvent.key!='message') return; // ignore other keys
    var message=JSON.parse(ev.originalEvent.newValue);
    if (!message) return; // ignore empty msg or msg reset

    // here you act on messages.
    // you can send objects like { 'command': 'doit', 'data': 'abcd' }
    if (message.command == 'doit') alert(message.data);

    // etc.
}

因此,一旦您的选项卡绑定在onstorage事件上,并且实现了这两个功能,您就可以简单地向其他调用的选项卡广播消息,例如:

message_broadcast({'command':'reset'})

请记住,两次发送完全相同的消息将只传播一次,因此,如果需要重复消息,请为其添加一些唯一标识符,如

message_broadcast({'command':'reset', 'uid': (new Date).getTime()+Math.random()})

还要记住,广播消息的当前选项卡实际上并不接收消息,只接收同一域上的其他选项卡或窗口。

您可能会问,如果用户加载不同的网页或在removeItem()之前的setItem()调用之后关闭他的选项卡,会发生什么情况。从我自己的测试来看,浏览器会暂停卸载,直到完成整个函数message_broadcast()。我测试将一些非常长的for()循环放入其中,但它仍然等待循环结束后才关闭。如果用户在两者之间删除了选项卡,那么浏览器将没有足够的时间将消息保存到磁盘,因此在我看来,这种方法就像是一种安全的方法,如何在没有任何痕迹的情况下发送消息。欢迎评论。

 类似资料:
  • 我使用以下方法打开带有一些页面内容的new tab(在new process中), http://news.softpedia.com/news/force-google-chrome-to-open-links-in-new-processes-128962.shtml 这起作用了,新的选项卡打开了mypage.html内容。 假设这是myPage(只是示例...)我应该如何访问它? 现在让我们

  • 问题内容: 我有两个窗口:窗口A和窗口B。 窗口A和窗口B具有相同的域 窗口A和窗口B没有任何父窗口。 问题: 窗口A是否可以获得窗口B的引用? 使窗口A通知窗口B的最优雅方法是什么? (包括新的HTML5规范) 我知道这样做的两种方式: 服务器发送消息:窗口B经常询问服务器,窗口A是否已通知某些内容 通过本地数据(HTML5)进行消息传递:当窗口A要通知其更改本地数据的内容时,窗口B会定期检查本

  • 问题内容: 我正在寻找一种方法,以在浏览器中的多个选项卡或窗口之间进行通信(在同一个域中,而不是在CORS上)而不会留下痕迹。 第一个可能是最糟糕的解决方案-您需要从当前窗口中打开一个窗口,然后您只能在保持窗口打开状态下进行通信。如果您在任何窗口中重新加载页面,则很可能失去了通信。 使用postMessage的第二种方法可能启用了跨域通信,但是遇到了与第一种方法相同的问题。您需要维护一个窗口对象。

  • 问题内容: 我正在寻找一种方法,以在浏览器中的多个选项卡或窗口之间进行通信(在同一个域中,而不是在CORS上)而不会留下痕迹。有几种解决方案: using window object postMessage cookies localStorage 第一个可能是最糟糕的解决方案-您需要从当前窗口中打开一个窗口,然后您只能在保持窗口打开状态下进行通信。如果您在任何窗口中重新加载页面,则很可能失去了通

  • 我正在学习本教程中的示例。根据教程,我想在两个选项卡之间拖动选项卡。到目前为止,我设法创建了这段代码,但我需要一些帮助才能完成代码。 来源 将选项卡的内容作为对象插入的正确方法是什么?简单的文本被转移到教程中。我必须如何修改这行< code>content.put(DataFormat。PLAIN_TEXT,tab pane);? 拖动选项卡后插入选项卡的正确方法是什么: 目的地 我想这个转移可以

  • 我已经搜索了很多关于如何使用SlidengTablayout在片段之间进行通信的内容,但还没有找到一个好的答案。我知道使用ActionBar,但我想要的是androidLollipop使用SlidingTabLayout的新方式。我试过了-