我动态创建了一个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);
为什么我终于是1? 如何防止iframe的onload两次而不是将onload函数指向内部为null?
答案 0 :(得分:44)
我也遇到了同样的问题,但在任何地方都没有答案,所以我自己测试了。
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
然后,您将只获得一个onload事件,这是文档真正加载的事件。
答案 1 :(得分:11)
扩展最高投票答案:如果你无法控制事物附加到DOM的时间和方式 - 例如,当使用框架时(我们已经发生了这种情况)我们的Angular app) - 你可能想尝试下面的解决方案。
我进行了大量的跨浏览器测试,我找到了以下解决方法:检查传递给onload
回调的参数并检查事件监听器中的evt.target.src
。
iframe.onload = function(evt) {
if (evt.target.src != '') {
// do stuff
}
}
(如果您从HTML调用全局方法,请记住在HTML标记中传递event
:<iframe onload="window.globalOnLoad(event)">
)
evt.target.src
只能在第一个''
调用的webkit中为onload
(空字符串)。
iframe.onload = function(evt){
console.log("frameOnload", ++i);
console.log("src = '" + evt.target.src + "'");
};
// 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/";
答案 2 :(得分:0)
FWIW,虽然在onload
为iframe.src
的情况下我能够重现双javascript:
,但我无法使用正常的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!
当我在追加之前指定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
答案 3 :(得分:0)
我曾经在异步加载的样式表中遇到过这种情况,
<link rel="preload" href="stylesheet.css" as="style" onload="this.rel='stylesheet'">
我发现最简单的解决方案是让事件自行删除:
<link rel="preload" href="stylesheet.css" as="style" onload="this.removeAttribute('onload'); this.rel='stylesheet'">
答案 4 :(得分:0)
这里的代码效果很好!
信用:@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>
答案 5 :(得分:0)
以@ jakub.g的答案为基础:
在框架内部,evt.target.src
hack不起作用。但是我发现我可以改为检查evt.target.title
。第二次触发DOMContentLoaded
时,evt.target
指向正在加载的文档,因此可以正常工作:
document.addEventListener('DOMContentLoaded', function(evt) {
if (evt.target.title !== myPageTitle) {
// Work around for Webkit browsers trigging this event twice om iframes
return
}
// DOM content loaded, for real
}
即使在Internet Explorer中,此行为似乎也是一致的(保存为没有.addEventListener
的旧版本
答案 6 :(得分:0)
我在 vue.js 2.6.12 中遇到过这个问题
我通过检查 event.target.url 是否与 iframe 的 onload 函数内的 src url 匹配来处理它。
MERGE INTO t
USING (SELECT 1 ID, _time'00:00:00' ts, 1234 col1, 3456 col2, 4567 col3 FROM rdb$database) AS d
ON t.ID = d.ID and t.col1 = d.col1 and t.col3 = d.col3
WHEN MATCHED UPDATE SET t.end_ts = d.ts, t.r_count = t.r_count + 1
WHEN NOT MATCHED INSERT (ID, ts, end_ts, r_count, col1, col2, col3) VALUES (d.ID, d.ts, d.ts, 1, d.col1, d.col2, d.col3)
答案 7 :(得分:0)
Register for onload event after appending iframe. This solves my problem.
document.body.appendChild(ifr);
ifr.onload=frameOnload;
E.G:
iframeContainer.appendChild(iframe)
iframe.onload = function() {
console.log("iframe onload called")
iframeContainer.appendChild(iframe)
iframe.onload = function() {
console.log("iframe onload called")
}
}