關(guān)于圖片的預(yù)加載過(guò)程中隱藏未知的
function loadImage(url, callback) {
var img = new Image(); //創(chuàng)建一個(gè)Image對(duì)象,實(shí)現(xiàn)圖片的預(yù)下載
img.src = url;
if (img.complete) { // 如果圖片已經(jīng)存在于瀏覽器緩存,直接調(diào)用回調(diào)函數(shù)
callback(img);
return; // 直接返回,不用再處理onload事件
}
img.onload = function () { //圖片下載完畢時(shí)異步調(diào)用callback函數(shù)。
callback(img);
};
};
在網(wǎng)上搜索了一下相關(guān)文章,大體上都是這個(gè)思路。
這個(gè)方法功能是ok的,但是有一些隱患。
1 創(chuàng)建了一個(gè)臨時(shí)匿名函數(shù)來(lái)作為圖片的onload事件處理函數(shù),形成了閉包。
相信大家都看到過(guò)ie下的內(nèi)存泄漏模式的文章,其中有一個(gè)模式就是循環(huán)引用,而閉包就有保存外部運(yùn)行環(huán)境的能力(依賴(lài)于作用域鏈的實(shí)現(xiàn)),所以img.onload這個(gè)函數(shù)內(nèi)部又保存了對(duì)img的引用,這樣就形成了循環(huán)引用,導(dǎo)致內(nèi)存泄漏。(這種模式的內(nèi)存泄漏只存在低版本的ie6中,打過(guò)補(bǔ)丁的ie6以及高版本的ie都解決了循環(huán)引用導(dǎo)致的內(nèi)存泄漏問(wèn)題)。
2 只考慮了靜態(tài)圖片的加載,忽略了gif等動(dòng)態(tài)圖片,這些動(dòng)態(tài)圖片可能會(huì)多次觸發(fā)onload。
要解決上面兩個(gè)問(wèn)題很簡(jiǎn)單,其實(shí)很簡(jiǎn)單,代碼如下:
img.onload = function () {
//圖片下載完畢時(shí)異步調(diào)用callback函數(shù)。
img.onload = null;
callback(img); };
這樣既能解決內(nèi)存泄漏的問(wèn)題,又能避免動(dòng)態(tài)圖片的事件多次觸發(fā)問(wèn)題。
在一些相關(guān)博文中,也有人注意到了要把img.onload 設(shè)置為null,只不過(guò)時(shí)機(jī)不對(duì),大部分文章都是在callback運(yùn)行以后,才將img.onload設(shè)置為null,這樣雖然能解決循環(huán)引用的問(wèn)題,但是對(duì)于動(dòng)態(tài)圖片來(lái)說(shuō),如果callback運(yùn)行比較耗時(shí)的話,還是有多次觸發(fā)的隱患的。
隱患經(jīng)過(guò)上面的修改后,就消除了,但是這個(gè)代碼還有優(yōu)化的余地:
if (img.complete) {
// 如果圖片已經(jīng)存在于瀏覽器緩存,直接調(diào)用回調(diào)函數(shù)
callback(img);
return; // 直接返回,不用再處理onload事件
}
關(guān)于這段代碼,看相關(guān)博文里的敘述,原因如下:
經(jīng)過(guò)對(duì)多個(gè)瀏覽器版本的測(cè)試,發(fā)現(xiàn)ie、opera下,當(dāng)圖片加載過(guò)一次以后,如果再有對(duì)該圖片的請(qǐng)求時(shí),由于瀏覽器已經(jīng)緩存住這張圖片了,不會(huì)再發(fā)起一次新的請(qǐng)求,而是直接從緩存中加載過(guò)來(lái)。對(duì)于 firefox和safari,它們?cè)噲D使這兩種加載方式對(duì)用戶透明,同樣會(huì)引起圖片的onload事件,而ie和opera則忽略了這種同一性,不會(huì)引起圖片的onload事件,因此上邊的代碼在它們里邊不能得以實(shí)現(xiàn)效果。
確實(shí),在ie,opera下,對(duì)于緩存圖片的初始狀態(tài),與firefox和safari,chrome下是不一樣的(有興趣的話,可以在不同瀏覽器下,測(cè)試一下在給img的src賦值緩存圖片的url之前,img的狀態(tài)),但是對(duì)onload事件的觸發(fā),卻是一致的,不管是什么瀏覽器。產(chǎn)生這個(gè)問(wèn)題的根本原因在于,img的src賦值與 onload事件的綁定,順序不對(duì)(在ie和opera下,先賦值src,再賦值onload,因?yàn)槭蔷彺鎴D片,就錯(cuò)過(guò)了onload事件的觸發(fā))。應(yīng)該先綁定onload事件,然后再給src賦值,代碼如下:
function loadImage(url, callback) {
var img = new Image(); //創(chuàng)建一個(gè)Image對(duì)象,實(shí)現(xiàn)圖片的預(yù)下載
img.onload = function(){
img.onload = null;
callback(img);
}
img.src = url;
}
這樣內(nèi)存泄漏,動(dòng)態(tài)圖片的加載問(wèn)題都得到了解決,而且也以統(tǒng)一的方式,實(shí)現(xiàn)了callback的調(diào)用。
- js實(shí)現(xiàn)的頁(yè)面加載完畢之前l(fā)oading提示效果完整示例【附demo源碼下載】
- jQuery頁(yè)面加載初始化的3種方法(推薦)
- 基于javascript實(shí)現(xiàn)頁(yè)面加載loading效果
- pace.js頁(yè)面加載進(jìn)度條插件
- php簡(jiǎn)單計(jì)算頁(yè)面加載時(shí)間的方法
- jQuery在頁(yè)面加載時(shí)動(dòng)態(tài)修改圖片尺寸的方法
- 頁(yè)面加載完后自動(dòng)執(zhí)行一個(gè)方法的js代碼
- 兩種方法實(shí)現(xiàn)在HTML頁(yè)面加載完畢后運(yùn)行某個(gè)js
- jquery實(shí)現(xiàn)在頁(yè)面加載完畢后獲取圖片高度或?qū)挾?/a>
- jQuery頁(yè)面加載初始化常用的三種方法
- 概述一個(gè)頁(yè)面從輸入U(xiǎn)RL到頁(yè)面加載完的過(guò)程
相關(guān)文章
詳解微信小程序?qū)崿F(xiàn)跑馬燈效果(附完整代碼)
這篇文章主要介紹了微信小程序跑馬燈效果,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-04-04JavaScript中校驗(yàn)銀行卡號(hào)的實(shí)現(xiàn)代碼
本文通過(guò)案例給大家介紹了js中校驗(yàn)銀行卡號(hào)的代碼,代碼小編測(cè)試過(guò),可行。代碼簡(jiǎn)單易懂,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友參考下吧2016-12-12使用JavaScript實(shí)現(xiàn)在頁(yè)面中顯示距離2017年中秋節(jié)的天數(shù)
這篇文章主要介紹了 使用JavaScript實(shí)現(xiàn)在頁(yè)面中顯示距離2017年中秋節(jié)的天數(shù)的相關(guān)資料,需要的朋友可以參考下2017-09-09跟我學(xué)習(xí)javascript的嚴(yán)格模式
跟我學(xué)習(xí)javascript的嚴(yán)格模式,對(duì)javascript嚴(yán)格模式進(jìn)行概述,進(jìn)入嚴(yán)格模式的方法,以及如何調(diào)用和相關(guān)語(yǔ)法,感興趣的小伙伴們可以參考一下2015-11-11利用JS延遲加載百度分享代碼,提高網(wǎng)頁(yè)速度
相信大家經(jīng)常在一些網(wǎng)站上看到有快捷分享到各大流行網(wǎng)站的按鈕,目前流行的有JiaThis、百度分享、Bshare等,目前用百度分享的居多2013-07-07七個(gè)基于JavaScript實(shí)現(xiàn)的情人節(jié)表白特效
情人節(jié)將至 程序員證明自己不是直男的時(shí)候到啦 我們也有自己的專(zhuān)屬代碼浪漫。本文將介紹七個(gè)利用JavaScript實(shí)現(xiàn)的情人節(jié)表白特效,需要的可以參考一下2022-01-01JavaScript選取(picking)和反選(rejecting)對(duì)象的屬性方法
這篇文章主要介紹了JavaScript選取(picking)和反選(rejecting)對(duì)象的屬性方法的相關(guān)資料,需要的朋友可以參考下2017-08-08js實(shí)現(xiàn)無(wú)縫循環(huán)滾動(dòng)
這篇文章主要為大家詳細(xì)介紹了js實(shí)現(xiàn)無(wú)縫循環(huán)滾動(dòng)的具體代碼,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2016-08-08