浏览器标签/窗口之间的Javascript通信

ada*_*Lev 144 javascript browser

在同一浏览器的选项卡/窗口之间进行Javascript通信的最可靠方法是什么?例如,当Tab 2开始音频播放时,Tab 1以某种方式知道这一点并且可以暂停它的播放器.

我正在建立一个带有音乐播放器的网站...所以,如果你打开两个标签到网站,你可以在两者上开始播放音乐.这显然很糟糕,所以我试图找到一个解决方案.

有任何想法吗?谢谢

bri*_*out 143

有关更现代的解决方案,请访问/sf/answers/876006911/

引用:

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

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

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

参考:
http://dev.w3.org/html5/webstorage/
http://dev.w3.org/html5/webstorage/#the-storage-event

  • 这比公认的解决方案更好.这不需要您不断检查新信息,没有延迟并使您能够接收所有事件. (4认同)
  • 好的演示页面 - http://html5demos.com/storage-events#view-source (3认同)
  • 我在IE11上遇到localStorage的问题,请看这篇文章(我面对第3点)http://blogs.msdn.com/b/ieinternals/archive/2009/09/16/bugs-in-ie8-support-for- html5-postmessage-sessionstorage-and-localstorage.aspx所以cockie soliution更好(至少IE).此外,我试图禁用cockies但它仍然工作(这是在IE 11). (2认同)

Rom*_*nko 92

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

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>
Run Code Online (Sandbox Code Playgroud)

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>
Run Code Online (Sandbox Code Playgroud)

  • 不要将字符串传递给`setTimeout` - 你正在使用`eval`这样做.相反,直接使用`setTimeout(updateMessage,100)`传递函数 (14认同)
  • 我也想过这样的东西,但希望有一个比cookies/setTimeout更好的解决方案.然而,这可能只是唯一的解决方案.谢谢 (2认同)
  • 我还建议使用`setInterval()` (2认同)

don*_*own 15

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

var w2 = window.open(...) 
Run Code Online (Sandbox Code Playgroud)

在w2中,您可以使用window的opener属性访问w1.

  • 大家都知道,这是答案是错误的,正如@Ferdinak已经试图说的那样.您没有对用户打开的选项卡的引用. (25认同)
  • 有趣是无关紧要的.这首先是问答网站.人们来到这个页面寻找提问者问题的答案.如果你想分享一些有趣的东西,你应该考虑写一个新的wiki风格的问题. (3认同)
  • @ jonas.ninja IMO问题并非100%清楚标签的打开方式,所以这是一个非常有效的答案,即使它不是一个普遍的答案. (3认同)
  • 使用COOKIES?吃它们,享受!有一个更简单的方法!只需访问其他窗口的var.在w1中得到一个值var,从w2 whit window.opener.value访问它! (2认同)
  • 假设用户打开它们.那种情况下有类似的解决方案吗 (2认同)

Leo*_*lev 13

还有一种称为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"});
Run Code Online (Sandbox Code Playgroud)

显然这是经验技术,并不是所有浏览器都支持.

  • 它不再是实验性的,即使 Edge 可能还没有实现它(它在 MDN 中被标记为“?”) (2认同)

Dav*_*han 11

您可以通过本地存储API执行此操作.请注意,这仅适用于2个选项卡.您不能将发件人和收件人放在同一页面上:

在发件人页面上:

localStorage.setItem("someKey", "someValue");
Run Code Online (Sandbox Code Playgroud)

在接收器页面上

    $(document).ready(function () {

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

        function storageEventHandler(evt) {
            alert("storage event called key: " + evt.key);
        }
    });
Run Code Online (Sandbox Code Playgroud)

  • 您无需等待DOM准备就绪即可访问localStorage (3认同)
  • 谢谢你的解决方案.让我的一天.它不适用于file:/// protocol,但适用于有效域.另一个类似的演示http://html5demos.com/storage-events (2认同)

Ash*_*wal 10

窗口下方(w1)打开另一个窗口(w2).任何窗口都可以向/从另一个窗口发送/接收消息.因此,我们应该理想地验证消息来自我们打开的窗口(w2).

在w1

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

在w2(abc.do)

window.opener.postMessage("Hi! I'm w2", "*");
Run Code Online (Sandbox Code Playgroud)


Vic*_*ard 9

如果它们具有子父关系,您可以在窗口之间进行通信(选项卡式或非选项卡式).

创建和更新子窗口:

<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>
Run Code Online (Sandbox Code Playgroud)

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

请在此处查看:https://jsbin.com/cokipotajo/edit?html,js,output


Mar*_*son 8

如果文档的来源相同,甚至在HTML5之前就支持在不同的JavaScript执行上下文之间进行通信.如果没有,或者您没有引用其他Window对象,那么您可以使用HTML5引入的新postMessage API.我在这个stackoverflow答案中详细阐述了两种方法.

  • postMessage API不是为http://stackoverflow.com/a/1100416/470117设计的.您需要引用目标窗口来发布该特定窗口的消息 (4认同)

归档时间:

查看次数:

133727 次

最近记录:

6 年,7 月 前