延遲加載(Lazyload)三種實現方式

原文連接 - https://zhuanlan.zhihu.com/p/25455672javascript

延遲加載也稱爲惰性加載,即在長網頁中延遲加載圖像。
用戶滾動到它們以前,視口外的圖像不會加載。
這與圖像預加載相反,在長網頁上使用延遲加載將使網頁加載更快。
在某些狀況下,它還能夠幫助減小服務器負載。css

延遲加載的優勢html

提高用戶的體驗,若是圖片數量較大,打開頁面的時候要將將頁面上全部的圖片所有獲取加載,極可能會出現卡頓現象,影響用戶體驗。所以,有選擇性地請求圖片,這樣能明顯減小了服務器的壓力和流量,也可以減少瀏覽器的負擔。java

方法一

  1. 將頁面上全部圖片的src屬性設置爲loading.gif,而圖片的真實路徑則設置在data-src屬性中。api

  2. 當頁面滾動的時候計算圖片位置和滾動的位置,當圖片出如今瀏覽器視口內時,將圖片的src屬性設置爲data-src的值。數組

<img src="loading.png" data-src="image.png">
img { display: block; margin-bottom: 50px; }
function lazyload() {
  var images = document.getElementsByTagName('img');
  var n  = 0; // 用於存儲圖片加載到的位置,避免每次都從第一張圖片開始遍歷    
  return function() {
    var seeHeight = document.documentElement.clientHeight;
    var scrollTop = document.documentElement.scrollTop || document.body.scrollTop;
    for(var i = n; i < images.length; i++) {
      if (images[i].offsetTop < seeHeight + scrollTop) {
        if (images[i].getAttribute('src') === 'loading.png') {
          images[i].src = images[i].getAttribute('data-src');
        }
        n = n + 1;
      }
    }
  }
}
lazyload(); //初始化首頁的頁面圖片
window.addEventListener('scroll', lazyload(), false);

方法二

上面的方法雖然沒什麼問題,可是性能較差,由於當頁面滾動時,scroll事件會高頻觸發,這很是影響瀏覽器性能。
因此,這裏要對lazyload函數進行函數節流(throttle)函數去抖(debounce)處理。瀏覽器

函數節流(throttle)與函數去抖(debounce)服務器

這裏html和css代碼不變,通過throttle處理的js代碼以下:函數

function throttle (fn, delay, atleast) {
  var timeout = null,
      startTime = new Date();
  return function () {
    var curTime = new Date();
    clearTimeout(timeout);
    if (curTime - startTime >= atleast) {
      fn ();
      startTime = curTime;
    } else {
      timeout = setTimeout (fn, delay);
    }
  }
}

function lazyload() {
  var images = document.getElementsByTagName('img'),
      n = 0;      //存儲圖片加載到的位置,避免每次都從第一張圖片開始遍歷   
  return function() {
    var seeHeight = document.documentElement.clientHeight;
    var scrollTop = document.documentElement.scrollTop || document.body.scrollTop;
    for(var i = n; i < images.length; i++) {
      if(images[i].offsetTop < seeHeight + scrollTop) {
        if(images[i].getAttribute('src') === 'loading.png') {
          images[i].src = images[i].getAttribute('data-src');
        }
        n = n + 1;
      }
    }
  }
}
lazyload(); //初始化首頁的頁面圖片
window.addEventListener('scroll', throttle(lazyload(), 500, 1000), false);

方法三

目前有一個新的 IntersectionObserver API,能夠自動"觀察"元素是否可見。性能

IntersectionObserver API 使用教程

用這種方法實現代碼很是簡潔,可是許多瀏覽器不支持。

圖片描述

  1. IntersectionObserver 傳入一個回調函數,當其觀察到元素集合出現時候,則會執行該函數。

  2. io.observe 即要觀察的元素,要一個個添加才能夠。

  3. io 管理的是一個數組,當元素出現或消失的時候,數組添加或刪除該元素,而且執行該回調函數。

function query(selector) {
  return Array.from(document.querySelectorAll(selector));
}
var io = new IntersectionObserver(function(items) {
  items.forEach(function(item) {
    var target = item.target;
    if(target.getAttribute('src') == 'loading.png') {
      target.src = target.getAttribute('data-src');
    }
  })
});
query('img').forEach(function(item) {
  io.observe(item);
});
相關文章
相關標籤/搜索