懶加載與預加載的基本概念。
懶加載也叫延遲加載:前一篇文章有介紹:JS圖片延遲加載 延遲加載圖片或符合某些條件時才加載某些圖片。 預加載:提前加載圖片,當用戶需要查看時可直接從本地緩存中渲染。 兩種技術的本質:兩者的行為是相反的,一個是提前加載,一個是遲緩甚至不加載。懶加載對服務器前端有一定的緩解壓力作用,預加載則會增加服務器前端壓力。 懶加載的意義及實現方式有: 意義: 懶加載的主要目的是作為服務器前端的優化,減少請求數或延遲請求數。 實現方式: 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或者火狐下測試 都是正常的 不管我怎麼刷新都是正常的,但是在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('http://img01.taobaocdn.com/imgextra/i1/397746073/T2BDE8Xb0bXXXXXXXX-397746073.jpg',function(){ alert('width:' + this.width + 'height:' + this.height); });