Динамически создаваемые iframe триггеры события onload дважды
Я создал 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 внутри себя?
Ответы
Ответ 1
Я также столкнулся с одной и той же проблемой, но не получаю ответа нигде, поэтому сам тестировал.
Событие onload iframe будет запускаться дважды в браузерах webkit (сафари/хром), если вы присоедините событие onload до того, как iframe будет добавлен в тело.
Таким образом, вы можете предотвратить onrame onload дважды, изменив свои коды следующим образом.
document.body.appendChild(ifr);
ifr.onload=frameOnload; // attach onload event after the iframe is added to the body
Затем вы получите только одно событие onload, которое является событием, которое действительно загрузило документ.
Ответ 2
Более подробно об ответе с наибольшим количеством голосов: если вы не можете контролировать, когда и как объекты подключаются к DOM - например, при использовании инфраструктуры (у нас это происходило в нашем приложении Angular), - вы можете захотеть попробуйте решение ниже.
Я провел evt.target.src
межбраузерное тестирование и нашел следующий обходной путь: проверьте параметр, переданный evt.target.src
onload
и проверьте evt.target.src
в evt.target.src
событий.
iframe.onload = function(evt) {
if (evt.target.src != '') {
// do stuff
}
}
(если вы вызываете глобальный метод из HTML, не забудьте передать event
в вашей разметке HTML: <iframe onload="window.globalOnLoad(event)">
)
evt.target.src
может быть ''
(пустая строка) только в webkit при первом вызове onload
.
Изучение поведения нагрузки iframe в различных ситуациях
iframe.onload = function(evt){
console.log("frameOnload", ++i);
console.log("src = '" + evt.target.src + "'");
};
поведение загрузки iframe с обычным 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 с 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 с неразрешимым (на уровне DNS) 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.src
onload с iframe.src
явно установленным в about:blank
перед добавлением в 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.src
onload с iframe.src
явно установленным на выражение javascript перед добавлением в 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
FWIW, в то время как я смог воспроизвести double onload
, в случае, если iframe.src
- javascript:
, я не смог воспроизвести его с помощью обычного HTTP-URL (одна загрузка выполнялась один раз). Однако при изменении порядка вызовов, чтобы 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
Ответ 4
У меня такое случалось с асинхронно загруженными таблицами стилей, как этот.
<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'">
Ответ 5
Вот код, который работает хорошо!
Предоставлено: @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>