检测iframe中加载的DOMContent

问题描述 投票:0回答:4

我惊讶地发现以下内容似乎不起作用,因为

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 级别 0

onload
是有效的。

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(); });

尽管如此,最好知道第一种方法的情况......

javascript events dom iframe domready
4个回答
36
投票

在回答这个问题的过程中,我发现了你的

DOMContentLoaded
事件监听器不起作用的原因。在我看来你有两个问题。

首先,您尝试监听 iFrame 本身上的

DOMContentLoaded
事件。这不是 iFrame 事件。这是一个文档事件。因此,您必须进入 iFrame 来获取 contentWindow,然后从中获取文档。这就引出了第二个问题。

其次,当首次创建 iFrame 时,其中有一个虚拟

document
,该文档与通过
.src
属性加载动态内容时最终出现的文档不同。所以,即使你这样做了:

this.els.stage_ifr.contentWindow.document

要获取 iFrame 中的文档,它不一定是正确的文档,因此

DOMContentLoaded
事件不会在其上触发(我在 Chrome 中看到过这种行为)。


MDN 表示可以监听 iFrame 本身上的

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


无论如何,我想我应该解释一下你的初始代码发生的一些事情,并提供另一个解决方案,即使这个问题是一年多前发布的(尽管从未得到回答)。


更新:

我开发了一种跟踪

DOMContentLoaded
的方法,用于加载与其父级具有相同来源的 iFrame。您可以在此处查看代码。


10
投票

尝试不同的选项后,我发现以下代码适合我:

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

2
投票

如果您的页面和 iframe 位于同一域中,您必须首先等待原始页面触发

DOMContentLoaded
,然后在 iframe 的
DOMContentLoaded
(不是
Window
)上附加一个
Document
事件侦听器。

假设您有一个 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!');
    });
});

1
投票

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

我现在正在听

onmouseenter
的框架内容。

此事件在

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

甚至当鼠标下的框架内容发生变化时也会触发。

© www.soinside.com 2019 - 2024. All rights reserved.