2 只考慮了靜態圖片的加載,忽略了gif等動態圖片,這些動態圖片可能會多次觸發onload。
要解決上面兩個問題很簡單,其實很簡單,代碼如下:
代碼如下:
img.onload = function () {
//圖片下載完畢時異步調用callback函數。
img.onload = null;
callback(img); };
這樣既能解決內存泄漏的問題,又能避免動態圖片的事件多次觸發問題。
在一些相關博文中,也有人注意到了要把img.onload 設置為null,只不過時機不對,大部分文章都是在callback運行以后,才將img.onload設置為null,這樣雖然能解決循環引用的問題,但是對于動態圖片來說,如果callback運行比較耗時的話,還是有多次觸發的隱患的。
隱患經過上面的修改后,就消除了,但是這個代碼還有優化的余地:
代碼如下:
if (img.complete) {
// 如果圖片已經存在于瀏覽器緩存,直接調用回調函數
callback(img);
return; // 直接返回,不用再處理onload事件
}
關于這段代碼,看相關博文里的敘述,原因如下:
經過對多個瀏覽器版本的測試,發現ie、opera下,當圖片加載過一次以后,如果再有對該圖片的請求時,由于瀏覽器已經緩存住這張圖片了,不會再發起一次新的請求,而是直接從緩存中加載過來。對于 firefox和safari,它們試圖使這兩種加載方式對用戶透明,同樣會引起圖片的onload事件,而ie和opera則忽略了這種同一性,不會引起圖片的onload事件,因此上邊的代碼在它們里邊不能得以實現效果。
確實,在ie,opera下,對于緩存圖片的初始狀態,與firefox和safari,chrome下是不一樣的(有興趣的話,可以在不同瀏覽器下,測試一下在給img的src賦值緩存圖片的url之前,img的狀態),但是對onload事件的觸發,卻是一致的,不管是什么瀏覽器。產生這個問題的根本原因在于,img的src賦值與 onload事件的綁定,順序不對(在ie和opera下,先賦值src,再賦值onload,因為是緩存圖片,就錯過了onload事件的觸發)。應該先綁定onload事件,然后再給src賦值,代碼如下:
代碼如下:
function loadImage(url, callback) {
var img = new Image(); //創建一個Image對象,實現圖片的預下載
img.onload = function(){
img.onload = null;
callback(img);
}
img.src = url;
}
這樣內存泄漏,動態圖片的加載問題都得到了解決,而且也以統一的方式,實現了callback的調用。
聲明:本網頁內容旨在傳播知識,若有侵權等問題請及時與本網聯系,我們將在第一時間刪除處理。TEL:177 7030 7066 E-MAIL:11247931@qq.com