首頁  >  文章  >  web前端  >  解析javascript圖片懶載入與預先載入的分析總結

解析javascript圖片懶載入與預先載入的分析總結

高洛峰
高洛峰原創
2016-12-08 15:17:161146瀏覽

這篇文章主要介紹了懶加載和預先加載兩種技術的解析,廢話不多說,一起來看吧。

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

預先載入:提前載入圖片,當使用者需要查看時可直接從本機快取渲染。

兩種技術的本質:兩者的行為是相反的,一個是提前加載,一個是遲緩甚至不加載。懶加載對伺服器前端有一定的緩解壓力作用,預先載入則會增加伺服器前端壓力。

懶載入的意義及實作方式有:

意義: 懶載入的主要目的是作為伺服器前端的最佳化,減少請求數或延遲請求數。

實作方式:

1.第一種是純粹的延遲加載,使用setTimeOut或setInterval進行加載延遲.

2.第二種是條件加載,符合某些條件,或觸發了某些事件才開始異步下載。

3.第三種是可視區加載,即​​僅加載用戶可以看到的區域,這個主要由監控滾動條來實現,一般會在距用戶看到某圖片前一定距離遍開始加載,這樣能保證用戶拉下時正好能看到圖片。

預先載入的意義及實現方式有:

預先載入可以說是犧牲伺服器前端效能,換取更好的使用者體驗,這樣可以使用戶的操作得到最快的反映。實作預載的方法非常多,可以用CSS(background)、JS(Image)、HTML(解析javascript圖片懶載入與預先載入的分析總結)都可以。常用的是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);
  }
}

   

為什麼其他瀏覽器正常的:其實原因很簡單,就是瀏覽器快取了,除了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(&#39;http://img01.taobaocdn.com/imgextra/i1/397746073/T2BDE8Xb0bXXXXXXXX-397746073.jpg&#39;,function(){
  alert(&#39;width:&#39; + this.width + &#39;height:&#39; + this.height);
});

   

以上就是本文的全部內容


陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn