动态创建的iframe触发onload事件两次

Lan*_*ton 26 javascript iframe

我动态创建了一个iframe,发现这个iframe触发onload事件两次.

var i=0;
frameOnload=function(){
  console.log(i++);  
};

var ifr=document.createElement("iframe");  
ifr.src="javascript:(function(){document.open();document.write('test');document.close();})();";
ifr.onload=frameOnload;  
document.body.appendChild(ifr);
Run Code Online (Sandbox Code Playgroud)

为什么我终于是1?
如何防止iframe的onload两次而不是将onload函数指向null本身?

Ben*_*ung 47

我也遇到过同样的问题,但在任何地方都没有答案,所以我自己测试了.

iframe onload事件将在webkit浏览器(safari/chrome)中触发两次,如果在iframe附加到正文之前附加onload事件.

因此,您可以通过以下方式更改代码来阻止iframe两次加载.

document.body.appendChild(ifr);
ifr.onload=frameOnload; // attach onload event after the iframe is added to the body
Run Code Online (Sandbox Code Playgroud)

然后,您将只获得一个onload事件,这是文档真正加载的事件.

  • 再一次,upvotes计算的不仅仅是答案 (2认同)
  • 天啊,我已经处理了这个问题大约六个月了.为什么这不是一个公认的答案?对于至少一岁的问题,SO众神应该自动接受具有高保票数的答案. (2认同)

jak*_*b.g 13

扩展最高投票的答案:如果你无法控制事物附加到DOM的时间和方式 - 例如,当使用框架时(我们已经在我们的Angular应用程序中发生了这种情况) - 你可能想要尝试下面的解决方案.

我做了大量的跨浏览器测试,我找到了以下解决方法:检查传递给onload回调的参数并检查evt.target.src事件监听器.

iframe.onload = function(evt) {
    if (evt.target.src != '') {
        // do stuff
    }
}
Run Code Online (Sandbox Code Playgroud)

(如果你从HTML调用全局方法,记得要通过event你的HTML标记:<iframe onload="window.globalOnLoad(event)">)

evt.target.src''在onload我的测试中,只能在第一次调用的webkit中使用(空字符串).

不同情况下iframe上下载行为的研究

iframe.onload = function(evt){
    console.log("frameOnload", ++i);
    console.log("src = '" + evt.target.src + "'");
};
Run Code Online (Sandbox Code Playgroud)

使用常规URL的iframe onload行为

// Chrome:  onload 1 src='', onload 2 src=requestedSrc
// IE11:    onload 1 src=requestedSrc
// Firefox: onload 1 src=requestedSrc
document.body.appendChild(iframe);
iframe.src = "http://www.example.org/";
Run Code Online (Sandbox Code Playgroud)

使用404 URL的iframe onload行为

// Chrome:  onload 1 src='', onload 2 src=requestedSrc
// IE11:    onload 1 src=requestedSrc
// Firefox: onload 1 src=requestedSrc
document.body.appendChild(iframe);
iframe.src = "http://www.example.org/404";
Run Code Online (Sandbox Code Playgroud)

具有不可解析(在DNS级别)URL的iframe onload行为

// Chrome:  onload 1 src='', onload 2 src=requestedSrc
// IE11:    onload 1 src=requestedSrc
// Firefox: onload NEVER triggered!
document.body.appendChild(iframe);
iframe.src= 'http://aaaaaaaaaaaaaaaaaaaaaa.example/';
Run Code Online (Sandbox Code Playgroud)

iframe onload行为,在附加到DOM之前iframe.src显式设置为about:blank

// Chrome:  onload 1 src='about:blank', onload 2 src=requestedSrc
// IE11:    onload 1 src=requestedSrc
// Firefox: onload 1 src=requestedSrc
iframe.src = "about:blank";
document.body.appendChild(iframe);
iframe.src = "http://www.example.org/";
Run Code Online (Sandbox Code Playgroud)

iframe onload行为,iframe.src在附加到DOM之前显式设置为javascript表达式

// Chrome:  onload 1 src='javascript:void 0', onload 2 src=requestedSrc
// IE11:    onload 1 src=requestedSrc
// Firefox: onload 1 src=requestedSrc
iframe.src = "javascript:void 0";
document.body.appendChild(iframe);
iframe.src = "http://www.example.org/";
Run Code Online (Sandbox Code Playgroud)