預先載入:提前載入圖片,當使用者需要查看時可直接從本機快取中渲染。
兩種技術的本質:兩者的行為是相反的,一個是提前載入,一個是遲緩甚至不載入。懶載入對伺服器前端有一定的緩解壓力作用,預先載入則會增加伺服器前端壓力。
懶載入的意義及實現方式有:
意義: 懶載入的主要目的是作為伺服器前端的最佳化,減少請求數或延遲請求數。
實現方式:
1.第一種是純粹的消極式載入,使用setTimeOut或setInterval進行載入延遲.
2.第二種是條件載入,符合某些條件,或觸發了某些事件才開始非同步下載。
3.第三種是可視區載入,即僅載入使用者可以看到的地區,這個主要由監控捲軸來實現,一般會在距使用者看到某圖片前一定距離遍開始載入,這樣能保證使用者拉下時正好能看到圖片。
預先載入的意義及實現方式有:
預先載入可以說是犧牲伺服器前端效能,換取更好的使用者體驗,這樣可以使使用者的操作得到最快的反映。實現預載的方法非常多,可以用CSS(background)、JS(Image)、HTML(<img />)都可以。常用的是new Image();,設定其src來實現預載,再使用onload方法回調預載完成事件。只要瀏覽器把圖片下載到本地,同樣的src就會使用緩衝,這是最基本也是最實用的預載方法。當Image下載完圖標題後,會得到寬和高,因此可以在預載前得到圖片的大小(方法是用記時器輪循寬高變化)。
怎麼樣才能實現預先載入?
我們可以通過google一搜尋:可以看到很多人用這種方式進行預先載入:代碼如下:
function loadImage(url,callback) {
var img = new Image();
img.src = url;
img.onload = function(){
img.onload = null;
callback.call(img);
}
}
在google或者Firefox下測試 都是正常的 不管我怎麼重新整理都是正常的,但是在IE6下不是這樣的 我點擊一下 是正常 再次點擊或者重新重新整理都不正常。下面的jsfiddle地址:有興趣的同學可以試試 點擊按鈕後 彈出正常結果 再次點擊在IE6下就不執行onload裡面的方法了,接著重新重新整理也不行。
想要看效果,點擊我!
為什麼其他瀏覽器正常的:其實原因很簡單,就是瀏覽器緩衝了,除了IE6以外(即說opera也會,但是我特意用opera試了下,沒有,可能版本的問題吧,或許現在已經修複了。),其他瀏覽器重新點擊會再次執行onload方法,但是IE6是直接從瀏覽器取的。
那現在怎麼辦?最好的情況是Image可以有一個狀態值表明它是否已經載入成功了。從緩衝載入的時候,因為不需要等待,這個狀態值就直接是表明已經下載了,而從http請求載入時,因為需要等待下載,這個值顯示為未完成。這樣的話,就可以搞定了。經過google搜尋下即介紹:發現有一個為各個瀏覽器所相容的Image的屬性——complete。所以,在圖片onload事件之前先對這個值做一下判斷即可。最後,代碼變成如下的樣子:
function loadImage(url,callback) {
var img = new Image();
img.src = url;
if(img.complete) { // 如果圖片已經存在於瀏覽器緩衝,直接調用回呼函數
callback.call(img);
return; // 直接返回,不用再處理onload事件
}
img.onload = function(){
img.onload = null;
callback.call(img);
}
}
也就是說如果圖片已經在瀏覽器緩衝裡面 那麼支援直接從瀏覽器緩衝取得直接執行img.complete裡面的函數 接著返回.
但是我們可以看到上面的代碼:必須等圖片載入完成後,可以執行回呼函數,也可以說等圖片載入後,我們可以擷取圖片的寬度和高度。那麼如果我們想提前擷取圖片的尺寸那怎麼辦?上網經驗告訴我:瀏覽器在載入圖片的時候你會看到圖片會先佔用一塊地然後才慢慢載入完畢,並且不需要預設width與height屬性,因為瀏覽器能夠擷取圖片的頭部資料。基於此,只需要使用javascript定時偵測圖片的尺寸狀態便可得知圖片尺寸就緒的狀態。代碼如下:(但是有個前提是 這個方式不是我想的,也不是我寫的代碼,是網上朋友總結的代碼 我只是知道有這麼一個原理)
var imgReady = (function(){
var list = [],
intervalId = null;
// 用來執行隊列
var queue = function(){
for(var i = 0; i < list.length; i++){
list[i].end ? list.splice(i--,1) : list[i]();
}
!list.length && stop();
};
// 停止所有定時器隊列
var stop = function(){
clearInterval(intervalId);
intervalId = null;
}
return function(url, ready, error) {
var onready = {},
width,
height,
newWidth,
newHeight,
img = new Image();
img.src = url;
// 如果圖片被緩衝,則直接返回快取資料
if(img.complete) {
ready.call(img);
return;
}
width = img.width;
height = img.height;
// 載入錯誤後的事件
img.onerror = function () {
error && error.call(img);
onready.end = true;
img = img.onload = img.onerror = null;
};
// 圖片尺寸就緒
var onready = function() {
newWidth = img.width;
newHeight = img.height;
if (newWidth !== width newHeight !== height
// 如果圖片已經在其他地方載入可使用面積檢測
newWidth * newHeight > 1024
) {
ready.call(img);
onready.end = true;
};
};
onready();
// 完全載入完畢的事件
img.onload = function () {
// onload在定時器時間差範圍內可能比onready快
// 這裡進行檢查並保證onready優先執行
!onready.end && onready();
// IE gif動畫會迴圈執行onload,置空onload即可
img = img.onload = img.onerror = null;
};
// 排入佇列中定期執行
if (!onready.end) {
list.push(onready);
// 無論何時只允許出現一個定時器,減少瀏覽器效能損耗
if (intervalId === null) {
intervalId = setInterval(queue, 40);
};
};
}
})();
調用方式如下:
imgReady('T2BDE8Xb0bXXXXXXXX-397746073.jpg',function(){
alert('width:' + this.width + 'height:' + this.height);
});