将DOMContentLoaded侦听器附加到动态创建的窗口

时间:2014-11-26 14:25:23

标签: javascript html5 javascript-events

由于我们的一些页面如何工作,JS可以随时注入页面,有时这个JS会关闭当前窗口。问题是我需要将一个事件监听器附加到窗口的onunload,以便可以从窗口返回一个值到父页面。但是因为可以在任何时候注入窗口关闭脚本,所以我不能将此事件绑定到onload,因为它的工作方式因此我希望使用DOMContentLoaded,因为该事件将在注入脚本之前触发。

但是在我的测试中,我无法在创建新窗口的父页面上绑定到DOMContentLoaded。

以下是我目前正在使用的内容:Plunker

我们目前只需要在Chrome中使用它。

我们当前的这种方法就像这样(伪代码):

onButtonClick = function(){
    win = window.open(...);
    win.onload = function(){
        win.onunload = function(){
            //Bind some function that will get the window's "return value" and pass it to the parent page
            //This will never happen if the window closes itself before the page is done loading
        };
    };
};

我可以使用DOMContentLoaded来实现我想要的吗?如果是这样,我该如何正确地将它附加到窗口?

注意:我无法绑定" onunload"一旦创建,就直接将事件发送到窗口。它似乎解雇了#on; onunload"事件两次(窗口打开时一次,关闭时一次)。如果你使用" bindOnCreate"你可以看到这种情况。功能在我的例子中。

2 个答案:

答案 0 :(得分:6)

如果您从

更改第58行
w.document.addEventListener('DOMContentLoaded', ...)

w.addEventListener('DOMContentLoaded', ...)

它有效。我将尝试解释实际情况下的实际情况:

  • 当窗口打开时,它最初具有URL about:blank。您可以通过在w.location.toString()事件处理程序中记录onunload来查看此信息(请参阅下一步)。
  • 之后,浏览器会立即加载window.open中提供的网址,从而触发onunload (第一次)about:blank
  • 具有不同window.document的真实页面被加载到弹出窗口中,但您的事件处理程序仍然在监听about:blank页面的DOM根目录,因为您向window.document添加了事件,而不是{{ 1}};现在,由于我们加载了另一个URL,window与之前的步骤完全不同。
  • 当您关闭窗口时,window.document会再次触发(第二次),因为您的onunload事件已连接到窗口

如果onunload用于弹出式addEventListener,则会收到来自所有window的事件,这些事件将因为JS事件冒泡机制而被加载到该窗口内。

我希望这能回答你的问题。

答案 1 :(得分:1)

或者,您可以从子窗口向其开启者发送消息,而不是让开启者处理子窗口的卸载事件。这将更容易,您不必担心注射点。此外,你可以摆脱两次卸载事件,因为Andrew Dunai已经说明了这个问题的原因。

这里我给出一个非常简单的演示,只显示我的消息传递解决方案的骨架:

<强> parent.html

<button id="open">Open Window</button>
<button id="close">Close Window</button>
<div></div>
<script>
  var child;

  document.querySelector('#open').addEventListener('click', function() {
    document.querySelector('div').innerHTML = '';
    child = window.open('child.html', 'child', 'width=600,height=600');
  }, false);

  document.querySelector('#close').addEventListener('click', function() {
    child.close();
  }, false);

  window.addEventListener('message', function(e) {
    document.querySelector('div').innerHTML = e.data;
  }, false);
</script>

<强> child.html

<input type="text" value="" placeholder="input something">
<script>
  window.addEventListener('beforeunload', function() {
    var msg = document.querySelector('input').value;
    window.opener.postMessage(msg, '*');
  }, false);
</script>

您可以通过单击其自己窗口的关闭按钮或父窗口中的按钮关闭子窗口,子输入中的值将始终发送给父级并显示。

这是我的一个项目的关键方法,并且运作良好。