Javascript圖片懶加載

原理

一開始將img標籤的src設置爲一張默認圖片,將真實的圖片地址放在data-src上,監聽滾動事件,當圖片進入可視區域時,寫入src真實的圖片地址。

如何判斷圖片進入了可視區域?

image.png
對於這樣一個頁面,圖片即將進入頁面的條件是:圖片距離整個網頁頂部的距離 < 瀏覽器可視區域的高度 + 滾動條滾動的距離。那麼問題就能夠分解成三個小點:css

①圖片距離整個網頁頂部的距離;

能夠經過下面這個方法獲取某個元素到網頁頂部的距離:html

function getElementTop (element) {
  let actualTop = element.offsetTop;
  let parent = element.offsetParent;

  while (parent !== null) {
    actualTop += parent.offsetTop;
    parent = parent.offsetParent;
  }

  return actualTop;
}

代碼分析:
offsetTop表示的是元素距離父元素左上角頂點的高度,offsetParent則表示元素的父元素。經過不斷遍歷累加高度,就能夠獲得元素距離網頁頂部的距離。瀏覽器

②瀏覽器可視區域的高度;

window.innerHeight閉包

③滾動條滾動的距離。

document.documentElement.scrollTopapp

懶加載如何實現?

html代碼以下:函數

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
    <link rel="stylesheet" href="./lazyLoad.css">
</head>
<body>
    <div class="wrapper">
        <img src="./default.jpg" data-src="./dog0.jpg">
        <img src="./default.jpg" data-src="./dog1.jpg">
        <img src="./default.jpg" data-src="./dog2.jpg">
        <img src="./default.jpg" data-src="./dog3.jpg">
        <img src="./default.jpg" data-src="./dog4.jpg">
        <img src="./default.jpg" data-src="./dog5.jpg">
        <img src="./default.jpg" data-src="./dog6.jpg">
    </div>
    <script src="./lazyLoad.js"></script>
</body>
</html>

這裏只須要注意到開始時img標籤的src屬性放的是默認的圖片,真正的圖片地址放在了data-src中性能

css代碼以下:優化

.wrapper {
    text-align: center;
}

img {
    display: block;
    margin: 10px auto;
}

js代碼以下:ui

function lazyLoad () {
  let images = document.querySelectorAll('img');
  for(let i = 0; i < images.length; i++) {
    let image = images[i];
    if (getElementTop(image) <= window.innerHeight + document.documentElement.scrollTop) {
      image.src = image.getAttribute('data-src');
    }
  }
}

function getElementTop (element) {
  let actualTop = element.offsetTop;
  let parent = element.offsetParent;

  while (parent !== null) {
    actualTop += parent.offsetTop;
    parent = parent.offsetParent;
  }

  return actualTop;
}

lazyLoad();

window.onscroll =lazyLoad;

代碼分析:
window.onscroll = lazyload表示在滾動條滾動時觸發調用lazyLoad方法;spa

在lazyLoad方法中,先經過document.querySelectorAll('img');找到全部的Image(這裏只是爲了簡化示例,實際場景中能夠經過在須要懶加載的圖片上添加統一的類名,而後經過querySelectorAll('.類名')來獲取須要懶加載的圖片),依次判斷是否進入了可視區域內。若是進入了可視區域則作img標籤的src的替換。

須要手動調用一次lazyLoad方法,在頁面剛load的時候將已經在視窗內的圖片加載出來。

函數節流

所謂的函數節流就是當事件觸發的頻率很高時,並非每次都須要去調用相對應的處理函數,以此來提升性能。好比這裏的滾動事件,假設咱們但願至少間隔200ms才調用一次處理函數,那麼能夠新增一個方法

function throttle (delay, action) {
  let last = 0;
  return function () {
    let now = new Date();
    if (now - last > delay) {
      action();
      last = now;
    }
  }
}

而後將window.onscroll =lazyLoad;改爲window.onscroll = throttle(200, lazyLoad)。這個函數在事件觸發時,先去判斷本次觸發的時間和上次觸發的時間的間隔,若是大於delay, 則運行處理函數。

函數用到了閉包的原理來保存last這個變量,對於閉包簡單的解釋一下就是throttle這個函數在調用結束後,原本應該銷燬掉其內部的last變量,可是因爲返回的是一個函數,返回的函數內引用了last這個變量,所以last被一直保存在了內存中。

throttle這個方法還有不少能夠優化的地方,不在這裏展開了。主題是懶加載嘛,後面有空了專門寫一篇函數節流方法的文章。

相關文章
相關標籤/搜索