在没有窗口参考的选项卡dom之间进行通信[重复]

Posted

技术标签:

【中文标题】在没有窗口参考的选项卡dom之间进行通信[重复]【英文标题】:Communicate between tabs dom without window ref [duplicate] 【发布时间】:2017-02-28 06:14:14 【问题描述】:

我使用以下内容打开包含一些页面内容的新选项卡(在新进程中),

var p = document.getElementById("myElement"); 
var a = document.createElement('a');
a.setAttribute('href',".../mypage.html");
a.setAttribute('rel',"noreferrer");
a.setAttribute('target',"_blank");
p.appendChild(a);
a.click();

http://news.softpedia.com/news/Force-Google-Chrome-to-Open-Links-in-New-Processes-128962.shtml

这正在工作,新标签页已打开,其中包含 myPage.html 内容。

假设这是 myPage(仅用于示例...)我应该如何访问它?

<!DOCTYPE html>
<html>
<body>

<h1> Heading</h1>
<p> paragraph.</p>
 <button type="button">Click Me!</button>

</body>
</html>

现在让我们进入棘手/高级:)部分...

当你使用window.open我不能使用)这很简单,因为你可以使用各种技术。

 1. using window object
 2. post message
 https://developer.mozilla.org/en-US/docs/Web/API/Window/postMessage
 3. cookies 
 4. localStorage

但在这里我打开这个新页面时没有使用 window.open 获得的参考

我的问题是:

如果我想更改某些内容,如何访问这个新的标签 dom

【问题讨论】:

嗨,我在发帖前给你 +1 搜索 @MarnyA.López - 谢谢 :) 我希望您对同源策略没有任何问题。 1)任何页面都可以是“父”吗? 2)您需要双向发送消息吗? (父母 -> 孩子或孩子 -> 父母) @fremail - 目前我没有域问题...我需要从“子选项卡”向“父选项卡”发送消息,如果您有想法请提供一些示例,谢谢! 你说你不能使用window.open API然后说你根本不能使用window?怎么会?要求避免 XY... 【参考方案1】:

父页面 javascript

var lastMessage;
setInterval(function() 
  var message = localStorage.getItem('message-to-parent');
  if (message && message !== lastMessage) 
    lastMessage = message;
    // your code here
    alert('There is a new message for you: ' + message);
  
, 100);

子页面 JavaScript:

localStorage.setItem('message-to-parent', 'hello, my parent!');

如果你有很多动画和其他巨大的JS代码,我建议增加定时器间隔,或者更好地解决问题window

【讨论】:

谢谢,这个解决方案将如何在浏览器中执行,我的意思是从性能或负载... @JohnJerrby 计时器将添加一个作业(回调函数)来检查消息,延迟为 100 毫秒,但问题是该作业可能会晚于 100 毫秒运行。在此处阅读更多关于 JS 计时器的信息ejohn.org/blog/how-javascript-timers-work 如果您使用 100 毫秒或更长的延迟并且间隔的回调函数很简单(如我的代码),您可能对性能保持冷静。 谢谢! ,我不确定我是否可以使用此解决方案,因为它不可靠...(正如您发布的链接所说...),您认为我可以使用其他解决方案吗? @JohnJerrby 您是否尝试使用此解决方案? ***.com/a/28230846/3816979 我读了这篇文章(我在我的问题上放了一个链接)但是有一个窗口 $(window).on('storage', message_receive); , 有一种方法可以将它绑定到其他东西上吗?如果这样可以很好,我可以使用它...【参考方案2】:

我遇到了类似的问题,并构建了一个小型库,以通过 localStorage 进行函数调用,并可以使用参数。你可以找到它here。 目前并非所有 browsers 都支持 Service Worker。

这是一个如何使用它的示例:

//Register a function: 
RegisterLocalStorageFunction("test", function(param) 
    return param+param; 
);

//Call a function: 
let str = "testing"; 
CallLocalStorageFunction("test",str,function(para) 
    console.log(para); 
);

在您的上下文中:

RegisterLocalStorageFunction("CallAlert", function(param) 
    alert(param);
    return "Success"; 
);
var p = document.getElementById("myElement");
var a = document.createElement('a');
a.setAttribute('href',".../mypage.html");
a.setAttribute('rel',"noreferrer");
a.setAttribute('target',"_blank");
p.appendChild(a);
a.click();

在您的另一个窗口中:

<!DOCTYPE html>
<html>
<body>
<h1> Heading</h1>
<p> paragraph.</p>
<button type="button" onclick="btnClick()">Click Me!</button>
<script>
    function btnclick()
        CallLocalStorageFunction("CallAlert","Hello from the other tab",function(para) 
            console.log("para"); 
        );

</script>
</body>
</html>

双方必须在同一个域,否则无法访问同一个localStorage。 使用我在 github 上的当前代码,我使用 setInterval 在存储中循环。 有一个storage event,它会被触发到所有其他选项卡和窗口,但不会触发到同一个选项卡。 我将重写库以对事件使用更简洁的方法,但现在这应该可以解决问题。

更新

在存储库中,您可以找到基于 'storage' 事件的 communicator2。

更新

Here 是托管的工作示例。请记住允许弹出窗口。

【讨论】:

谢谢,如果您能在我的上下文中举例说明,如果您需要其他信息...谢谢! 谢谢 :),我现在试试,让你知道... 没问题,我推荐版本 2。如果您有任何问题,请告诉我。 谢谢,但我不能使用版本 2,因为你使用那里的窗口,我没有窗口对象,因为我使用 a.setAttribute('href',".../mypage.html"); a.setAttribute('rel',"noreferrer"); a.setAttribute('target',"_blank");但也许我想念一些…… 是的,但是由于我们在使用本地存储时遇到了一些安全问题,我正在尝试检查是否可以使用从安全方面更好的 sessionStorage,如果您知道如何使其与会话一起使用存储请告诉我。非常感谢!【参考方案3】:

您必须在触发 click 事件之前附加一个 DOMNodeInserted-listener,然后您才能访问此窗口对象。

// assuming that all inserted alements are links or a-tags
// this code must run before the code that adds the a-element
document.addEventListener("DOMNodeInserted", function (ev) 
      var link = ev.target;
      var oldRef = link.href;
      link.onclick = function(event)
        event.preventDefault();
        var childWindow = window.open(oldRef);
        childWindow.onload = function()
          console.log('at this point you can interact with this newly opened window-object: ',childWindow);
        ;
      ;
);

//...
// some other code
//...

var p = document.getElementById("myElement"); 
var a = document.createElement('a');
a.setAttribute('href',".../mypage.html");
a.setAttribute('rel',"noreferrer");
a.setAttribute('target',"_blank");
p.appendChild(a);
a.click();

希望这会有所帮助。

【讨论】:

谢谢,但我不能使用打开窗口...:(我只能使用 a.tag... 请试一试:)【参考方案4】:

您可以使用SharedWorker 在不同的浏览上下文之间进行通信。

见Can we refer to javascript variables across webpages in a browser session?

您也可以使用storage 事件Can the mechanism that loads the worker in Shared Web Workers be modified?

【讨论】:

以上是关于在没有窗口参考的选项卡dom之间进行通信[重复]的主要内容,如果未能解决你的问题,请参考以下文章

JavaScript;具有相同来源的选项卡/窗口之间的通信[重复]

JavaScript;具有相同来源的选项卡/窗口之间的通信[重复]

在同一域上的不同窗口之间进行通信[重复]

您如何在两个浏览器选项卡/窗口之间进行通信? [复制]

您如何在两个浏览器选项卡/窗口之间进行通信? [复制]

浏览器窗口之间是不是可以进行基于事件的通信? [复制]