检测iframe中的DOMContentLoaded

Utk*_*nos 10 javascript iframe events dom domready

我很惊讶地发现以下似乎不起作用,因为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);
Run Code Online (Sandbox Code Playgroud)

该页面加载到iframe中,但没有回调.onload但是,DOM级别为零.

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

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

Paraent页面:

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

框架页面:

$(function() { window.parent.dfd.resolve(); });
Run Code Online (Sandbox Code Playgroud)

尽管如此,知道第一种方法是什么还是很好的...

jfr*_*d00 19

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

首先,您正试图DOMContentLoaded在iFrame上监听事件.那不是iFrame事件.这是一个文件活动.因此,您必须进入iFrame才能获取contentWindow,然后从中获取文档.这导致了第二个问题.

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

this.els.stage_ifr.contentWindow.document
Run Code Online (Sandbox Code Playgroud)

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


MDN说,人们可以DOMFrameContentLoaded在iFrame上监听事件,这将与基础文档实际获得的时间相对应DOMContentLoaded.不幸的是,我无法在任何浏览器中使用此事件.所以,在这一刻,我所知道的唯一解决方法是从iFrame本身触发load事件,它可以监听自己的DOMContentLoaded事件(如果需要可以调用父窗口)或者只是load在iFrame对象上侦听事件,并知道在加载iFrame中的样式表和图像等资源之前不会触发它.


无论如何,我想我会解释你的初始代码发生了什么,并提供另一个解决方案,即使这个问题是在一年多前发布的(虽然没有回答).


更新:

我开发了一种跟踪DOMContentLoadediFrame 的方法,该iFrame加载了与其父级相同的原点.你可以在这里看到代码.

  • 我已经在问自己为什么 Chrome 中的“readyState”总是“已完成”。现在我知道这是因为 Chrome 设置了一个空文档并在此之后创建了实际的 iframe 文档(与 src 属性相关)。如此糟糕的行为,如果 Chrome 能像其他浏览器一样处理这种情况,我们可以简单地使用“readyState”。 (2认同)
  • `DOMFrameContentLoaded` 不仅是一个 [Mozilla 特定事件](https://developer.mozilla.org/en-US/docs/Web/Events#Mozilla-specific_events),也是一个“附加特定事件”,它“永远不会暴露于网络内容,只能在 Chrome 内容上下文中使用”。 (2认同)

小智 5

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

var iframe = document.getElementById("app-frame-id");
iframe.contentWindow.addEventListener("DOMContentLoaded", onFrameDOMContentLoaded, true);
function onFrameDOMContentLoaded () { 
     console.log("DOMContentLoaded");
};
Run Code Online (Sandbox Code Playgroud)

  • 当您更改iframe的源时,这不起作用 (2认同)