检测何时加载iframe内容(跨浏览器)


90

我正在尝试检测何时已加载iframe及其内容,但运气不佳。我的应用程序在父窗口的文本字段中进行了一些输入,并更新了iframe以提供“实时预览”

我从以下代码(YUI)开始,以检测何时发生iframe加载事件。

$E.on('preview-pane', 'load', function(){
    previewBody = $('preview-pane').contentWindow.document.getElementsByTagName('body')[0];
}

“预览窗格”是我的iframe的ID,我正在使用YUI附加事件处理程序。但是,我认为尝试通过回调(在iframe加载时)访问主体失败,我认为是因为iframe在事件处理程序准备好之前就已加载。如果我通过使生成iframe的php脚本进入睡眠状态来延迟iframe的加载,则此代码有效。

基本上,我想问的是跨浏览器检测iframe何时加载及其文档准备就绪的正确方法是什么?


1
与其他任何JS库一样,从YUI开始是一个坏主意。为什么?因为您只是不知道该库在做什么。如果他们不能完全支持“加载”,则最好使用清晰易读的JavaScript自己完成。
基督教徒

2
您通常可以阅读@Christian库的源代码。我发现这通常为您提供有关如何自己执行操作的重要提示,无论您是否随后使用它们的实现。
AJP

@AJP您误解了我的意思。如果您不确定自己要做什么,最好减少代码数量,以减少出错的空间。
基督教徒

2
取决于您如何看待它。我知道当时YUI的事件处理有效,所以我不必担心代码的那部分。我也知道如何编写自己的addEvent处理程序,就这个问题而言,它不比YUI更好。
David Snabel-Caunt

1
@Nico这个问题涉及YUI,而$是YUI的Dom包装器的别名。
David Snabel-Caunt 2014年

Answers:


73

检测何时安装iframe并准备好其文档?

理想的情况是,您可以通过框架内的脚本让iframe告诉您自己。例如,它可以直接调用父函数以告知它已准备就绪。跨框架代码执行始终需要谨慎,因为事情可能会以您不期望的顺序发生。另一种选择是设置“ var isready = true;” 在自己的范围内,并为'contentWindow.isready'制作父脚本(如果没有,则添加onload处理程序)。

如果由于某种原因让iframe文档进行合作不切实际,那么您就会遇到传统的负载竞争问题,即,即使元素彼此相邻也是如此:

<img id="x" ... />
<script type="text/javascript">
    document.getElementById('x').onload= function() {
        ...
    };
</script>

无法保证脚本执行时不会加载该项目。

摆脱负载竞争的方法是:

  1. 在IE上,您可以使用“ readyState”属性来查看是否已加载某些内容;

  2. 如果仅允许启用JavaScript的项目可用,则可以动态创建它,在设置源和附加到页面之前设置'onload'事件函数。在这种情况下,无法在设置回调之前加载它。

  3. 将其包含在标记中的老式方法:

    <img onload="callback(this)" ... />

HTML中的内联“ onsomething”处理程序几乎总是错误的事情,应该避免,但在这种情况下,有时这是最糟糕的选择。


谢谢。我的解决方案检查readyState(如果存在),然后检查body元素的innerHTML长度,以查看是否已加载。如果不是,则附加加载事件处理程序。似乎工作确定
大卫Snabel-Caunt

8
-1-内联事件并不“不好”,这只是当前的流行。实际上,与魔术事件不同,内联事件更易于调试和理解(另一方面,内联事件更易于附加,堆叠和无缝使用)。
基督教徒

1
@Christian,当需要将事件附加到非常长的列表的每个元素时,内联事件也是最佳选择。由于您已经在服务器端循环构建列表,因此附加内联事件的效率也大大提高。
haknick

16
@haknick您是否不想在列表上使用单个事件侦听器,并使用事件委托?这样会更有效率。
David Snabel-Caunt 2011年

4
如果iframe是跨域的,则此方法将无效。iframe中的脚本无法访问父窗口。
Sudheer Someshwara

48

请参阅博客文章。它使用jQuery,但即使您不使用它也应该对您有所帮助。

基本上,您将此添加到您的 document.ready()

$('iframe').load(function() {
    RunAfterIFrameLoaded();
});

有趣,但是我遇到的问题是负载事件和计时。我正在听这篇文章建议的load事件。
David Snabel-Caunt 09年

我已经尝试过了console.log。加载iframe后,它会被记录下来。
shorif2000

12

对于使用React的用户来说,检测同源iframe加载事件就像onLoad在iframe元素上设置事件监听器一样简单。

<iframe src={'path-to-iframe-source'} onLoad={this.loadListener} frameBorder={0} />


能否onLoad事件只能触发同源的iframe?
L_K

2

对于使用Ember的任何人,这应该可以正常工作:

<iframe onLoad={{action 'actionName'}}  frameborder='0' src={{iframeSrc}} />
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.