【问题标题】:Attach DOMContentLoaded listener to dynamically created window将 DOMContentLoaded 侦听器附加到动态创建的窗口
【发布时间】:2014-11-26 14:25:22
【问题描述】:

由于我们某些页面的工作方式,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”事件一旦创建就不能直接绑定到窗口。它似乎触发了两次“onunload”事件(一次在窗口打开时,一次在关闭时)。如果您在我的示例中使用“bindOnCreate”函数,您会看到这种情况。

【问题讨论】:

    标签: javascript html javascript-events


    【解决方案1】:

    如果您将第 58 行从

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

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

    它有效。我将尝试解释幕后实际发生的事情:

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

    如果您addEventListener 用于弹出窗口的window,它会接收来自所有window.document-s 的事件,这些事件将由于JS 事件冒泡机制而加载到该窗口中。

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

    【讨论】:

      【解决方案2】:

      或者,您可以从子窗口向其打开器发送消息,而不是让打开器处理子窗口的卸载事件。这会容易得多,您无需担心注入点。你也可以摆脱两次卸载事件,因为 Andrew Dunai 已经给出了这个问题的原因。

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

      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>
      

      无论是通过单击自己窗口的关闭按钮,还是通过父窗口中的按钮关闭子窗口,子窗口输入中的值将始终发送给父窗口并呈现。

      这是我的一个副项目的关键方法,效果很好。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2021-09-06
        • 1970-01-01
        • 1970-01-01
        • 2012-09-01
        • 1970-01-01
        • 2013-06-03
        • 2013-01-27
        相关资源
        最近更新 更多