iframe onload事件觸發兩次

標準參考

關於 HTML 4.01 規範中 onload 內在事件說明:http://www.w3.org/TR/html401/interact/scripts.html#adef-onloadhtml

關於 DOM Level2 Events 規範中 load 事件說明:http://www.w3.org/TR/DOM-Level-2-Events/events.html#Events-eventgroupings-htmlevents瀏覽器

問題描述

插入空白頁面 IFRAME 元素時 Chrome Safari Opera 瀏覽器中會觸發 load 事件。緩存

形成的影響

Chrome Safari Opera 瀏覽器中,在插入 "src" 屬性未設置或設置爲空字符串的 IFRAME 元素後當即修改其 "src" 屬性值,會致使 IFRAME 標記綁定的 load 事件再被觸發。app

觸發 IE 和 Firefox 瀏覽器中 IFRAME 標記 "src" 屬性值的歷史記錄問題。spa

受影響的瀏覽器

全部瀏覽器  

問題分析

根據規範說明,load 事件能夠做用於 FRAMESET 標記中,所以一樣也能夠做用於 IFRAME 標記上。它表示着 IFRAME 內頁面已經徹底加載完畢 IFRAME 標記處於可用狀態。htm

若是建立的 IFRAME 標記沒有設定 "src" 屬性和值,那麼他的 load 事件是否會被觸發呢?事件

分析如下代碼:ip

function iframeLoad(){
  alert("IFRAME 標記的 onload 事件觸發");
}
function addEvent(eventName,element,fn){
  if (element.attachEvent) element.attachEvent("on"+eventName,fn);
  else element.addEventListener(eventName,fn,false);
}
window.onload = function (){
  var iframe = document.createElement('iframe');
  addEvent("load",iframe,iframeLoad);
  document.body.appendChild(iframe);
  iframe.src="iframe.html";

}

代碼中動態建立了 IFRAME 標記,爲其監聽 load 事件,此時尚未顯示性的設定他的 "src" 值就將他加入文檔樹中。此後當即爲 IFRAME 設置 "src" 屬性,指向具體的 URL 。element

觀察各瀏覽器中運行效果:文檔

  IE Firefox Chrome Safari Opera
IFRAME onload 事件觸發次數 1次 2次

看到 Chrome Safari Opera 中 onload 事件被觸發兩次。

爲了搞清這個問題,咱們須要知道沒有設置 src 屬性的 IFRAME 被添加到 DOM 樹中後,其默認的 "src" 值是什麼。繼續分析如下代碼:

function iframeLoad(iframe){
  document.body.appendChild(document.createTextNode("IFRAME URL : "+iframe.location.href));
}
function addEvent(eventName,element,fn){
  if (element.attachEvent) element.attachEvent("on"+eventName,fn);
  else element.addEventListener(eventName,fn,false);
}
window.onload = function (){
  var iframe = document.createElement('iframe');
  addEvent("load",iframe,function (){iframeLoad(iframe.contentWindow)});
  document.body.appendChild(iframe);
}
  全部瀏覽器
URL about:blank

這 裏將空 src 值 IFRAME 標記內調用頁面的 URL 打印出來,能夠發現全部瀏覽器中處理一致,均爲 "about:blank" 。這個頁面是個空 HTML 文檔頁,全部瀏覽器均內置提供。這個空頁面被加載完成後一樣會觸發 IFRAME 標記的 onload 事件。

由 此能夠推測,是否因爲 Chrome Safari Opera 瀏覽器中當 IFRAME 標記被插入文檔樹後,載入"about:blank" 頁面速度很是快當即就觸發了 load 事件,以致於還沒來得及執行爲他指定新 URL 的語句;當新 URL 指定後,當前頁面加載完成時又觸發了一次 IFRAME 標記的 load 事件,這樣總共就觸發了兩次。

而其餘瀏覽器則是載入 "about:blank" 頁花費時間加多,頁面並未徹底加載時其 URL 已經被改變,所以相對 Chrome Safari Opera 瀏覽器第一次 load 事件並無觸發,只有等新 URL 中的頁面加載完畢後 load 事件才被觸發,這樣總共只觸發了一次。

爲了證實以上猜想,將一段延時執行的代碼加入其中:

function iframeLoad(iframe){
  var src = (iframe.src)?iframe.src:iframe.contentWindow.location.href;
  document.body.appendChild(document.createElement("br"));
  document.body.appendChild(document.createTextNode("IFAME 標記 src 值爲 "+ src + " 的 onload 事件觸發"));
}
function addEvent(eventName,element,fn){
  if (element.attachEvent) element.attachEvent("on"+eventName,fn);
  else element.addEventListener(eventName,fn,false);
}
window.onload = function (){
  var iframe = document.createElement('iframe');
  addEvent("load",iframe,function (){iframeLoad(iframe)});
  iframe.src= "about:blank";
  document.body.appendChild(iframe);
  setTimeout(function (){iframe.src="iframe.html";},300)
}

代碼中,在 IFRAME 節點被添加到文檔樹樹後,延時 300 毫秒再改變它的 src 屬性,以便給其餘瀏覽器充足的事件將 "about:blank" 頁面加載完成。

此時各瀏覽器執行結果一致:

  全部瀏覽器
IFRAME onload 事件觸發次數 'about:blank' 頁面1次
'iframe.html' 頁面1次
共2次

這 個結果證實了以前的猜測:Chrome Safari Opera 瀏覽器執行速度比想象中的要快的多,致使好像「多」觸發了一次 load 事件,實際上全部瀏覽器均會爲 IFRAME 標記內每一個頁面觸發他的 load 事件,前提是讓這些頁面有足夠的事件加載完成。

【注】:使用appendChild 方法將沒有設置 src 屬性的 IFRAME 插入文檔樹和使用 innnerHTML 方式將沒有寫 src 屬性的 IFRAME 標記字符串插入文檔樹時,均會存在以上分析的問題。

 

最後來看,上面的代碼中在插入節點以前爲 IFRAME 標記顯式性的設置了 src 屬性值爲 "about:blank" 的頁面,這是爲了不 Firefox 中 URL 緩存的 Bug。

在 IE 和 Firefox 中,若是 IFRAME 沒有顯示性的設置 "src" ,若是該頁面第一次被打開,則實際頁面的 src 值爲 "about:blank";不然將爲 IFRME 標記中最後一個被設定的 "src" 值。

分析如下代碼(沒有明肯定義 src 屬性值):

window.onload = function (){
  var iframe = document.createElement('iframe');
  addEvent("load",iframe,function (){iframeLoad(iframe)});
  document.body.appendChild(iframe);
  setTimeout(function (){iframe.src="iframe.html";},300)
}

注意代碼 "src" 值最初未定義,最終被修改成 "ifarme.html",觀察在各瀏覽器中運行結果:

  Chrome Safari Opera IE Firefox
首次顯示 'about:blank' 頁 onload 事件觸發
'iframe.html' 頁 onload 事件觸發
F5 普通刷新 'about:blank' 頁 onload 事件觸發
'iframe.html' 頁 onload 事件觸發
'iframe.html' 頁 onload 事件觸發
'iframe.html' 頁 onload 事件觸發
Ctrl + F5 強制刷新 'about:blank' 頁 onload 事件觸發
'iframe.html' 頁 onload 事件觸發

可見,IE 和 Firefox 瀏覽器中出現了 IFRAME 元素的 "src" 屬性最後指向的記憶問題,普通刷新頁面後,沒有明確設置 "src" 屬性的 IFRAME 標記將默認使用上一條歷史記錄中的 "src" 值。

解決方案

爲 IFRAME 標籤的 src 屬性指定具體 URL 後再將節點插入 DOM 樹中 。

本文轉自:http://www.w3help.org/zh-cn/causes/SD9019

相關文章
相關標籤/搜索