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

时间:2022-10-22 07:53:59

I created an iframe dynamically and found that this iframe trigger onload event twice.

我动态创建了一个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);

Why i finally is 1?
How to prevent iframe's onload twice instead of pointing onload function to null inside itself?

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

3 个解决方案

#1


40  

I've also encountered the same problem, but get no answer anywhere, so I tested by myself.

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

The iframe onload event will be triggered twice in webkit browsers ( safari/chrome ), if you attach the onload event BEFORE the iframe is appended to the body.

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

So you can prevent iframe onload twice by change your codes in the following way.

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

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

Then, you will only get one onload event, which is the event the document really loaded.

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

#2


8  

I did heavy cross-browser testing and I found another workaround: check the parameter passed to onload callback and inspect evt.target.src in the event listener.

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

iframe.onload = function(evt) {
    if (evt.target.src != '') {
        // do stuff
    }
}

(if you call global method from HTML, remember to pass event in your HTML markup: <iframe onload="window.globalOnLoad(event)">)

(如果从HTML调用全局方法,请记住在HTML标记中传递事件:

This is handy if you can not control when and how things are attached to the DOM, for instance, when using a framework (we've had this happening in our Angular app).

如果你无法控制事物附加到DOM的时间和方式,这很方便,例如,当使用框架时(我们已经在Angular应用程序中发生了这种情况)。

evt.target.src can be be '' (empty string) only in webkit in the first onload call, from my tests.

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

Study of iframe onload behavior in different situations

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

iframe onload behavior with regular URL

// 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/";

iframe onload behavior with 404 URL

// 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";

iframe onload behavior with non-resolvable (at DNS level) URL

// 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/';

iframe onload behavior with iframe.src explicitly set to about:blank before appending to DOM

// 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/";

iframe onload behavior with iframe.src explicitly set to a javascript expression before appending to DOM

// 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/";

#3


0  

FWIW, while I was able to reproduce double onload in case where iframe.src is javascript:, I was not able to reproduce it with a normal HTTP URL (onload was happening once). However, when you change the order of calls so that iframe.src is set after appending to body, then the double-load happens (again, webkit only):

FWIW,虽然我能够在iframe.src是javascript:的情况下重现双重onload,但是我无法使用普通的HTTP URL重现它(onload发生了一次)。但是,当您更改调用顺序以便在追加到body之后设置iframe.src时,则会发生双重加载(同样,仅限webkit):

var i = 0;

var iframe = document.createElement("iframe");
iframe.onload = function(){
  console.log("frameOnload", ++i);
};
document.body.appendChild(iframe);
iframe.src = "http://www.example.org/";
//iframe.src = "http://www.example.org/404";

// double onload!

When I assign src before appending, I get one onload call.

当我在追加之前分配src时,我得到一个onload调用。

var i = 0;

var iframe = document.createElement("iframe");
iframe.onload = function(){
  console.log("frameOnload", ++i);
};
iframe.src = "http://www.example.org/";
//iframe.src = "http://www.example.org/404";
document.body.appendChild(iframe);

// only one onload

#1


40  

I've also encountered the same problem, but get no answer anywhere, so I tested by myself.

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

The iframe onload event will be triggered twice in webkit browsers ( safari/chrome ), if you attach the onload event BEFORE the iframe is appended to the body.

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

So you can prevent iframe onload twice by change your codes in the following way.

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

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

Then, you will only get one onload event, which is the event the document really loaded.

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

#2


8  

I did heavy cross-browser testing and I found another workaround: check the parameter passed to onload callback and inspect evt.target.src in the event listener.

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

iframe.onload = function(evt) {
    if (evt.target.src != '') {
        // do stuff
    }
}

(if you call global method from HTML, remember to pass event in your HTML markup: <iframe onload="window.globalOnLoad(event)">)

(如果从HTML调用全局方法,请记住在HTML标记中传递事件:

This is handy if you can not control when and how things are attached to the DOM, for instance, when using a framework (we've had this happening in our Angular app).

如果你无法控制事物附加到DOM的时间和方式,这很方便,例如,当使用框架时(我们已经在Angular应用程序中发生了这种情况)。

evt.target.src can be be '' (empty string) only in webkit in the first onload call, from my tests.

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

Study of iframe onload behavior in different situations

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

iframe onload behavior with regular URL

// 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/";

iframe onload behavior with 404 URL

// 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";

iframe onload behavior with non-resolvable (at DNS level) URL

// 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/';

iframe onload behavior with iframe.src explicitly set to about:blank before appending to DOM

// 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/";

iframe onload behavior with iframe.src explicitly set to a javascript expression before appending to DOM

// 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/";

#3


0  

FWIW, while I was able to reproduce double onload in case where iframe.src is javascript:, I was not able to reproduce it with a normal HTTP URL (onload was happening once). However, when you change the order of calls so that iframe.src is set after appending to body, then the double-load happens (again, webkit only):

FWIW,虽然我能够在iframe.src是javascript:的情况下重现双重onload,但是我无法使用普通的HTTP URL重现它(onload发生了一次)。但是,当您更改调用顺序以便在追加到body之后设置iframe.src时,则会发生双重加载(同样,仅限webkit):

var i = 0;

var iframe = document.createElement("iframe");
iframe.onload = function(){
  console.log("frameOnload", ++i);
};
document.body.appendChild(iframe);
iframe.src = "http://www.example.org/";
//iframe.src = "http://www.example.org/404";

// double onload!

When I assign src before appending, I get one onload call.

当我在追加之前分配src时,我得到一个onload调用。

var i = 0;

var iframe = document.createElement("iframe");
iframe.onload = function(){
  console.log("frameOnload", ++i);
};
iframe.src = "http://www.example.org/";
//iframe.src = "http://www.example.org/404";
document.body.appendChild(iframe);

// only one onload