Javascript 动态创建的 iframe 两次触发 onload 事件
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/10781880/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
dynamically created iframe triggers onload event twice
提问by Lanston
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?
回答by Ben P.P. Tung
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 事件,则 iframe onload 事件将在 webkit 浏览器 ( safari/chrome ) 中触发两次。
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 事件,也就是文档真正加载的事件。
回答by jakub.g
To expand on the top-voted answer: 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) -- you might want to try the solution below.
扩展最高投票的答案:如果您无法控制事物附加到 DOM 的时间和方式——例如,在使用框架时(我们的 Angular 应用程序中已经发生过这种情况)——您可能想要试试下面的解决方案。
I did heavy cross-browser testing and I found the following 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调用全局方法,记得要通过event
你的HTML标记:<iframe onload="window.globalOnLoad(event)">
)
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行为研究
iframe.onload = function(evt){
console.log("frameOnload", ++i);
console.log("src = '" + evt.target.src + "'");
};
iframe onload behavior with regular URL
带有常规 URL 的 iframe 加载行为
// 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
带有 404 URL 的 iframe 加载行为
// 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
具有不可解析(在 DNS 级别)URL 的 iframe 加载行为
// 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
在附加到 DOM 之前iframe.src
显式设置为的iframe 加载行为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/";
iframe onload behavior with iframe.src
explicitly set to a javascript expression before appending to DOM
iframe.src
在附加到 DOM 之前显式设置为 javascript 表达式的iframe 加载行为
// 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/";
回答by Ophion
I've had this happen to asynchronously loaded stylesheets, like this one.
我在异步加载的样式表上遇到过这种情况,比如这个。
<link rel="preload" href="stylesheet.css" as="style" onload="this.rel='stylesheet'">
I find that the simplest solution is to have the event remove itself:
我发现最简单的解决方案是让事件自行删除:
<link rel="preload" href="stylesheet.css" as="style" onload="this.removeAttribute('onload'); this.rel='stylesheet'">
回答by inon
Here code that works good!
这里的代码很好用!
Credit: @Dave Stolie https://coderanch.com/t/443223/languages/Frames-loading-refresh
信用:@Dave Stolie https://coderanch.com/t/443223/languages/Frames-loading-refresh
<html>
<head>
<script type="text/javascript">
function loadFrame()
{
var url="http://www.google.com";
alert(document.getElementById("theFrame").src);
if (document.getElementById("theFrame").src != url)
{
alert("loading");
document.getElementById("theFrame").src = url;
}
}
</script>
</head>
<body onLoad="loadFrame();">
<iframe id="theFrame" src="x"/>
</body>
</html>
回答by jakub.g
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,虽然我能够onload
在 where iframe.src
is 的情况下重现 double javascript:
,但我无法使用普通的 HTTP URL 重现它(onload 发生一次)。但是,当您更改调用顺序以便iframe.src
在附加到 body 之后设置时,就会发生双重加载(同样,仅适用于 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.
当我在 append 之前分配时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