javascript 检测 iframe 中的 DOMContentLoaded
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/16960829/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Detect DOMContentLoaded in iframe
提问by Utkanos
I was surprised to find the following doesn't appear to work, insofar as the DOMContentLoaded event doesn't fire (this.els
is an object of elements).
我很惊讶地发现以下内容似乎不起作用,因为 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);
The page loads into the iframe fine, but no callback. The DOM level zero onload
, however, works.
页面加载到 iframe 中,但没有回调。onload
然而,DOM level zero有效。
this.els.stage_ifr[0].onload = function() { alert('loaded!'); }; //<-- fires
A workaround is to prepare a globally-accessible jQuery deferred object in the parent page and resolve it via a DOM-ready event fired from the page called into the iframe, rather than listening for DOM-ready from the parent.
解决方法是在父页面中准备一个全局可访问的 jQuery 延迟对象,并通过从调用到 iframe 的页面触发的 DOM-ready 事件解析它,而不是从父页面监听 DOM-ready。
Paraent page:
父页面:
dfd = new $.Deferred;
dfd.done(function() { alert("frame page's DOM is ready!"); });
Frame page:
框架页面:
$(function() { window.parent.dfd.resolve(); });
Nonetheless it would be good to know what's up with the first approach...
尽管如此,最好知道第一种方法的情况......
回答by jfriend00
In the process of answering this question, I discovered the reason your DOMContentLoaded
event listener doesn't work. It appears to me that you have two issues.
在回答这个问题的过程中,我发现了你的DOMContentLoaded
事件监听器不起作用的原因。在我看来,你有两个问题。
First, you're trying to listen for the DOMContentLoaded
event on the iFrame itself. That isn't an iFrame event. It is a document event. So you have to reach into the iFrame to get the contentWindow and then get the document from that. That leads into the second issue.
首先,您正在尝试侦听DOMContentLoaded
iFrame 本身的事件。那不是 iFrame 事件。这是一个文档事件。因此,您必须进入 iFrame 以获取 contentWindow,然后从中获取文档。这就引出了第二个问题。
Second, when an iFrame is first created, it has a dummy document
in it that is NOT the same document as will eventually be there when dynamic content is loaded via the .src
attribute. So, even if you did:
其次,当 iFrame 首次创建时,其中有一个虚拟document
文件,该文件与通过.src
属性加载动态内容时最终存在的文件不同。所以,即使你做了:
this.els.stage_ifr.contentWindow.document
to get the document in the iFrame, it will not necessarily be the right document and thus the DOMContentLoaded
event won't fire on it (I've seen this behavior in Chrome).
要在 iFrame 中获取文档,它不一定是正确的文档,因此DOMContentLoaded
不会触发事件(我在 Chrome 中看到过这种行为)。
MDN says that one can listen for the DOMFrameContentLoaded
event on the iFrame itself and this will correspond with when the underlying document actually gets DOMContentLoaded
. Unfortunately, I can't get this event to work in any browser. So, at this moment, the only work-around I know of is to either trigger the load event from within the iFrame itself where it can listen to its own DOMContentLoaded
event (it can call out to the parent window if need be) or to just listen for the load
event on the iFrame object and know that it won't fire until resources such as style sheets and images in the iFrame are also loaded.
MDN 说可以DOMFrameContentLoaded
在 iFrame 本身上监听事件,这将与底层文档实际获取DOMContentLoaded
. 不幸的是,我无法在任何浏览器中使用此事件。因此,目前,我所知道的唯一解决方法是从 iFrame 本身内部触发加载事件,在那里它可以侦听自己的DOMContentLoaded
事件(如果需要,它可以调用父窗口)或只是侦听load
iFrame 对象上的事件,并知道在加载 iFrame 中的样式表和图像等资源之前它不会触发。
Anyway, I thought I'd explain some of what was going on with your initial code and offer another solution even though this question was posted more than a year ago (though never answered).
无论如何,我想我会解释一些你的初始代码发生了什么,并提供另一个解决方案,即使这个问题是一年多前发布的(虽然从未回答)。
Update:
更新:
I've developed a method of tracking DOMContentLoaded
for an iFrame loaded with the same origin as its parent. You can see the code here.
我开发了一种跟踪DOMContentLoaded
iFrame的方法,该 iFrame 加载的来源与其父级相同。您可以在此处查看代码。
回答by ivan.ice
After trying different options I found that the following code works for me:
在尝试了不同的选项后,我发现以下代码对我有用:
var iframe = document.getElementById("app-frame-id");
iframe.contentWindow.addEventListener("DOMContentLoaded", onFrameDOMContentLoaded, true);
function onFrameDOMContentLoaded () {
console.log("DOMContentLoaded");
};
回答by JochenJung
This might be more of a hack, but helped me solve a similar issue.
这可能更像是一种黑客攻击,但帮助我解决了类似的问题。
I am listening for onmouseenter
of the frame content now.
我现在正在监听onmouseenter
框架内容。
This event triggers ahead of load
(if the user moves the mouse). But as in my case I need the event for initialising a context menu, using the mouse was a precondition anyway.
此事件提前触发load
(如果用户移动鼠标)。但在我的情况下,我需要初始化上下文菜单的事件,无论如何使用鼠标是一个先决条件。
It even triggers when the frame content changes under the mouse.
它甚至会在鼠标下的框架内容发生变化时触发。
回答by Daniel
If your page and the iframe are on the same domainyou have to wait for the original page to fire DOMContentLoaded
first, then attach a DOMContentLoaded
event listener on the iframe's Window
(not Document
).
如果您的页面和 iframe在同一个域中,您必须先等待原始页面触发DOMContentLoaded
,然后DOMContentLoaded
在 iframe 的Window
(不是Document
)上附加一个事件侦听器。
Given you have an iframe as follows,
鉴于您有一个 iframe,如下所示,
<iframe id="iframe-id" name="iframe-name" src="..."></iframe>
the next snippet will allow you to hook into the iframe's DOMContentLoaded
event:
下一个片段将允许您挂接到 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!');
});
});