javascript圖片懶加載與預加載的分析

懶加載與預加載的基本概念。javascript

  懶加載也叫延遲加載:前一篇文章有介紹:JS圖片延遲加載 延遲加載圖片或符合某些條件時才加載某些圖片。html

   預加載:提早加載圖片,當用戶須要查看時可直接從本地緩存中渲染。前端

 兩種技術的本質:二者的行爲是相反的,一個是提早加載,一個是遲緩甚至不加載。懶加載對服務器前端有必定的緩解壓力做用,預加載則會增長服務器前端壓力。java

 懶加載的意義及實現方式有:瀏覽器

   意義: 懶加載的主要目的是做爲服務器前端的優化,減小請求數或延遲請求數。緩存

   實現方式: 服務器

      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);});

相關文章
相關標籤/搜索