18

我惊讶地发现以下似乎不起作用,因为 DOMContentLoaded 事件没有触发(this.els是元素的对象)。

this.els.stage_ifr.prop('src', 'templates/'+ee.globals.creating+'/item'+this.id);
this.els.stage_ifr[0].addEventListener('DOMContentLoaded', function() {
    alert('loaded!');
}, false);

页面加载到 iframe 中很好,但没有回调。然而, DOM level zeroonload可以工作。

this.els.stage_ifr[0].onload = function() { alert('loaded!'); }; //<-- fires

一种解决方法是在父页面中准备一个全局可访问的 jQuery 延迟对象,并通过调用 iframe 的页面触发的 DOM-ready 事件来解决它,而不是从父页面监听 DOM-ready。

父页面:

dfd = new $.Deferred;
dfd.done(function() { alert("frame page's DOM is ready!"); });

框架页面:

$(function() { window.parent.dfd.resolve(); });

尽管如此,最好知道第一种方法是怎么回事......

4

4 回答 4

32

在回答这个问题的过程中,我发现了你的DOMContentLoaded事件监听器不起作用的原因。在我看来,您有两个问题。

首先,您尝试DOMContentLoaded在 iFrame 本身上监听事件。这不是 iFrame 事件。这是一个文档事件。因此,您必须进入 iFrame 以获取 contentWindow,然后从中获取文档。这就引出了第二个问题。

其次,当第一次创建 iFrame 时,其中有一个虚拟文件,它与通过属性document加载动态内容时最终会出现的文件不同。.src所以,即使你这样做了:

this.els.stage_ifr.contentWindow.document

要在 iFrame 中获取文档,它不一定是正确的文档,因此DOMContentLoaded不会触发事件(我在 Chrome 中看到了这种行为)。


MDN 表示可以DOMFrameContentLoaded在 iFrame 本身上侦听事件,这将与底层文档实际获取的时间相对应DOMContentLoaded。不幸的是,我无法让这个事件在任何浏览器中工作。所以,目前,我知道的唯一解决方法是从 iFrame 本身触发加载事件,它可以在其中监听自己的DOMContentLoaded事件(如果需要,它可以调用父窗口)或者只是监听loadiFrame 对象上的事件并知道它不会触发,直到 iFrame 中的样式表和图像等资源也被加载。


无论如何,我想我会解释一下你的初始代码发生了什么,并提供另一个解决方案,即使这个问题是一年多前发布的(尽管从未回答过)。


更新:

我开发了一种跟踪DOMContentLoaded加载与其父级相同来源的 iFrame 的方法。您可以在此处查看代码。

于 2014-07-08T00:25:09.917 回答
9

在尝试了不同的选项后,我发现以下代码对我有用:

var iframe = document.getElementById("app-frame-id");
iframe.contentWindow.addEventListener("DOMContentLoaded", onFrameDOMContentLoaded, true);
function onFrameDOMContentLoaded () { 
     console.log("DOMContentLoaded");
};
于 2015-08-07T06:37:00.580 回答
2

如果您的页面和 iframe在同一个域上,您必须先等待原始页面触发,然后在 iframe (不是)上DOMContentLoaded附加一个DOMContentLoaded事件侦听器。WindowDocument

鉴于您有如下 iframe,

<iframe id="iframe-id" name="iframe-name" src="..."></iframe>

下一个片段将允许您挂钩 iframe 的DOMContentLoaded事件:

document.addEventListener('DOMContentLoaded', function () {
    var iframeWindow = frames['iframe-name'];
    // var iframeWindow = document.querySelector('#iframe-id').contentWindow
    // var iframeWindow = document.getElementById('iframe-id').contentWindow

    iframeWindow.addEventListener('DOMContentLoaded', function () {
        console.log('iframe DOM is loaded!');
    });
});
于 2020-03-09T22:42:42.303 回答
1

这可能更像是一种黑客攻击,但帮助我解决了类似的问题。

我现在正在收听onmouseenter框架内容。

此事件提前触发load(如果用户移动鼠标)。但在我的情况下,我需要事件来初始化上下文菜单,无论如何使用鼠标都是先决条件。

它甚至会在鼠标下的帧内容发生变化时触发。

于 2017-12-01T10:01:00.527 回答