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