在同一浏览器的选项卡/窗口之间进行Javascript通信的最可靠方法是什么?例如,当标签2开始音频播放,标签1莫名其妙地知道这一点,可以暂停的球员。

我建立了音乐播放器网站...所以此刻,如果你打开该网站的两个标签中,您可以同时在两个标签页上播放音乐。

有什么想法吗?
谢谢

评论

无论如何,自动播放音频都是不好的。为什么不让用户单击“播放”按钮,并在遇到这种情况时手动暂停其他选项卡?

没有自动播放功能。但是,如果用户不必手动暂停其他选项卡,那就太好了。 YouTube就是这样做的例子(带闪光灯)

+1好的问题,我现在正在我的网站聊天应用程序中解决这个确切的问题。

stackoverflow.com/questions/19125823/…

质量职位。 5年后仍然有用。

#1 楼

这是一个旧答案,我建议使用此处描述的现代版本:

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


您可以使用cookie在浏览器窗口之间(也可以与选项卡)进行通信。

以下是发送方和接收方的示例:

sender.html

<h1>Sender</h1>

<p>Type into the text box below and watch the text 
   appear automatically in the receiver.</p>

<form name="sender">
<input type="text" name="message" size="30" value="">
<input type="reset" value="Clean">
</form>

<script type="text/javascript"><!--
function setCookie(value) {
    document.cookie = "cookie-msg-test=" + value + "; path=/";
    return true;
}
function updateMessage() {
    var t = document.forms['sender'].elements['message'];
    setCookie(t.value);
    setTimeout(updateMessage, 100);
}
updateMessage();
//--></script>


receiver.html:

<h1>Receiver</h1>

<p>Watch the text appear in the text box below as you type it in the sender.</p>

<form name="receiver">
<input type="text" name="message" size="30" value="" readonly disabled>
</form>

<script type="text/javascript"><!--
function getCookie() {
    var cname = "cookie-msg-test=";
    var ca = document.cookie.split(';');
    for (var i=0; i < ca.length; i++) {
        var c = ca[i];
        while (c.charAt(0)==' ') c = c.substring(1,c.length);
        if (c.indexOf(cname) == 0) {
            return c.substring(cname.length, c.length);
        }
    }
    return null;
}
function updateMessage() {
    var text = getCookie();
    document.forms['receiver'].elements['message'].value = text;
    setTimeout(updateMessage, 100);
}
updateMessage();
//--></script>


评论


我也想到了类似的方法,但是希望有一个比cookie / setTimeout更好的解决方案。但是,这可能只是唯一的解决方案。谢谢

–adamJLev
2010年11月2日,16:03

不要将字符串传递给setTimeout-您正在通过eval进行操作。而是直接使用setTimeout(updateMessage,100)传递函数

–易江
2010年11月6日,下午2:40

我也建议使用setInterval()

–朱利安·F·韦纳特(Julian F. Weinert)
2014年7月3日15:49

我在IE11上遇到了localStorage的问题,请参阅此帖子(我面对第3点)blogs.msdn.com/b/ieinternals/archive/2009/09/16/…因此,解决方案更好(至少对于IE)。我也尝试禁用自拍,但它仍然起作用(这在IE 11,IE 10,IE 9上)。

–Anas
2015年11月3日,12:43

TomášZato,要知道答案是从2010年开始的-当时并不是所有浏览器都支持HTML5,而IE6和IE7的份额却很高。现在有更好的解决方案。

–罗马·戈扬科
17年2月7日在15:42

#2 楼

有关更现代的解决方案,请访问https://stackoverflow.com/a/12514384/270274
引用:

我坚持使用问题qq1202079q 。就可靠性,性能和浏览器兼容性而言,这似乎是最佳的解决方案。
localStorage已在所有现代浏览器中实现。
当其他选项卡对localStorage进行更改时,会触发storage事件。这对于进行通讯非常方便。
参考:http://dev.w3.org/html5/webstorage/http://dev.w3.org/html5/webstorage/#the-storage-event


评论


这比公认的解决方案好。这不需要您不断检查新信息,没有延迟,并使您能够接收所有事件。

– Stephane Mathis
15-10-16在14:11

我在IE11上遇到了localStorage的问题,请参阅此帖子(我面对第3点)blogs.msdn.com/b/ieinternals/archive/2009/09/16/…因此,解决方案更好(至少对于IE)。我也尝试禁用自拍,但它仍然起作用(这在IE 11上)。

–Anas
2015年11月3日,10:33



良好的演示页面-html5demos.com/storage-events#view-source

–HockeyJ
16年6月9日在8:02

@Anas:链接已死。新网址:blogs.msdn.microsoft.com/ieinternals/2009/09/15/…

– Tim Down
17年7月20日在8:18

这解决了很多问题(实现的范围比BroadcastChannel更广泛),但是请注意,如果用户在同一浏览器中打开2个“发送者”标签,您会感到有些惊讶:拥有1个公共通讯渠道可能会引起一些惊喜

– Xenos
19年1月16日在10:04

#3 楼

我认为您不需要cookie。每个文档的js代码都可以访问其他文档元素。因此,您可以直接使用它们共享数据。
您的第一个窗口w1打开w2并保存引用。

窗口的属性。

评论


使用Cookie?吃他们享受!有一种更简单的方法!只需访问另一个窗口的变量即可。在w1中有一个值var,可以从w2的window.opener.value中访问它!

–donkeydown
2012年2月7日在18:03



假设用户将其全部打开。在这种情况下有类似的解决方案吗?

–法尔丁K.
2012年12月2日上午8:26

就像所有人都知道的那样,答案是错误的,就像@Ferdinak已经尝试说的那样。您没有对用户打开的选项卡的引用。

– DDS
13年6月22日在21:53

有趣是无关紧要的。这首先是一个问答网站。人们来此页面寻找对提问者问题的答案。如果您想分享有趣的事情,则应考虑编写一个新的Wiki风格的问题。

– ivanjonas
2014年12月4日20:21



@ jonas.ninja IMO,问题是不是100%清楚如何打开选项卡,因此,即使这不是一个通用答案,这也是一个非常有效的答案。

–超极
16年4月19日在11:33

#4 楼

还有一种称为Broadcast Channel API的实验技术,专门用于起源相同的不同浏览器上下文之间的通信。您可以在不引用其他浏览器上下文的情况下向其发布消息和从其他浏览器上下文接收消息:

var channel = new BroadcastChannel("foo");
channel.onmessage = function( e ) {
  // Process messages from other contexts.
};
// Send message to other listening contexts.
channel.postMessage({ value: 42, type: "bar"});


显然,这是一种体验技术,尚不支持所有浏览器。

评论


它不再是实验性的,甚至是Edge可能尚未实现(在MDN中标记为?)

– Xenos
19年1月16日在10:02

Edge现在拥有了。

–Doin
7月28日22:04

#5 楼

您可以通过本地存储API执行此操作。请注意,这仅在2个标签之间有效。您不能将发送方和接收方放在同一页上:

在发送方页上:

localStorage.setItem("someKey", "someValue");


在接收方页上

    $(document).ready(function () {

        window.addEventListener('storage', storageEventHandler, false);

        function storageEventHandler(evt) {
            alert("storage event called key: " + evt.key);
        }
    });


评论


在发现webbrowser控件不会触发“存储”事件处理程序方法之前,我将使用此方法。不知道为什么。虫子。

– Brain2000
15年6月15日在22:23

感谢您的解决方案。让我开心。它不适用于file:///协议,但适用于有效域。另一个类似的演示html5demos.com/storage-events

– Vikram Kumar
16-3-28在20:28



您无需等待DOM准备就绪即可访问localStorage

–风度
17年8月13日在23:30

#6 楼

在窗口(w1)下方打开另一个窗口(w2)。任何窗口都可以向另一个窗口发送消息或从另一个窗口接收消息。因此,理想情况下,我们应该验证消息是否源自打开的窗口(w2)。

在w1中

var w2 = window.open("abc.do");
window.addEventListener("message", function(event){
    console.log(event.data);
});


在w2(abc。做)

window.opener.postMessage("Hi! I'm w2", "*");


评论


好的答案,应该有更多的投票权。

–VAdaihiep
17年9月29日在8:40

可以在所有浏览器上使用吗?

– Stepan Yakovenko
17年11月25日在7:14

@StepanYakovenko对浏览器的支持:developer.mozilla.org/en-US/docs/Web/API/Window/…

–阿什温·阿格瓦尔(Ashwin Aggarwal)
18年11月30日在12:05

#7 楼

如果窗口之间有子母关系,则可以在窗口之间进行通信(是否选中)。

创建和更新子窗口:

<html>
<head>
<title>Cross window test script</title>
<script>
var i = 0;
function open_and_run() {
    var w2 = window.open("", "winCounter"); 
    var myVar=setInterval(function(){myTimer(w2)},1000);
}

function myTimer(w2) {
    i++;
    w2.document.body.innerHTML="<center><h1>" + i + "</h1><p></center>";
}
</script>
</head>
<body>
Click to open a new window 
<button onclick="open_and_run();">Test This!</button>    
</body>
</html>


子窗口可以使用parent对象与产生它的父窗口进行通信,因此您可以从任一窗口控制音乐播放器。

在这里查看其运行情况:https://jsbin.com/cokipotajo/edit?html,js,output

评论


这里的一个问题是,我们不能(没有漏洞)共享到我们同步视图的链接...

– yckart
2015年3月10日13:41



@yckart有很多方法可以做到这一点,但是我见过的最常见的方法是将字符串发送到另一个窗口的输入框中。您可以使事件侦听器更改值。例如:stackoverflow.com/questions/9994120/…。我认为最好在另一个窗口中调用javascript函数,并将其传递给URL。例如,子窗口中的或父窗口中的

– Victor Stoddard
16 Mar 23 '16 at 1:15