實現懶加載的幾種方式(一)

1. 什麼是懶加載?

當咱們碰到長網頁有不少圖片時,咱們會採用先加載出如今視口內的幾張圖片,當滾動條滾動到相應圖片的位置時纔去加載別的圖片。這種延遲加載的方式咱們就稱之爲懶加載。html

2. 懶加載的優勢

  • 提高用戶體驗

    假設一個場景:當咱們瀏覽淘寶的時候,頁面須要加載很長時間才能顯示出來,根據3秒鐘定律,此時用戶確定已經失去了耐心。可是使用懶加載就可以大大提高頁面的展示速度,從而提高用戶體驗。git

  • 減輕服務器壓力

    想象一下,若是一我的須要在短期內作不少事情,那這我的確定壓力會很大。服務器也是同樣的,咱們經過懶加載就減輕了服務器的工做量,讓它有時間緩一緩,再來處理後面的事情。github

3. 實現原理

前面鋪墊了這麼多,下面重點來了(敲黑板!!!)。api

  • clientHeight:瀏覽器視口的高度;
  • scrollTop:滾動軸滾動的距離;
  • offsetTop:圖片的頭部距離瀏覽器頂部的高度(注意不是距離視口頂部的高度);

咱們實現懶加載的想法是一開始只加載顯示在視口內的圖片,從上圖能夠看出,咱們能夠先只加載前兩張圖片。那麼如何保證圖片不加載出來呢?瀏覽器

能夠經過將圖片的地址保存在img元素的自定義屬性上面,當須要加載的時候再將該自定義屬性賦值給該圖片的src性能優化

那麼問題來了,何時加載後面的圖片呢?bash

就是在咱們滾動滾動軸的時候,當下一張圖片的頂部立刻要出如今視口的時候去加載下一張圖片。服務器

好啦,如今咱們已經知道該什麼去加載下一張圖片了。那麼接下來是第二個問題:怎麼知道下一張圖片立刻要出如今視口上了呢?dom

就是當圖片距離瀏覽器頂部的高度---即offsetTop <= 視口高度clientHeight + 滾動條的長度scrollTop這是重點!!!明白了這個後面就簡單了函數

最後一個問題,如何獲取offsetTopscrollTopclientHeight這三個數值呢?

  • offsetTop:直接經過img.offsetTop就能夠獲取;
  • scrollTop:經過document.documentElement.scrollTop獲取;
  • clientHeight:經過document.documentElement.clientHeight獲取;

此處主要介紹懶加載,對於上述三個api不熟悉可自行百度學習。建議先記住他們能夠這麼獲取就行。

4. 代碼實現

  • 首先定義html結構和CSS樣式;
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <style>
    img {
      height: 450px;
      display: block;
      margin-bottom: 20px;
    }
  </style>
</head>
<body>
  <!--圖片地址暫時先保存在data-src這個自定義屬性上面-->
  <img data-src="./img-loop/img/1.jpg" alt="懶加載1" />
  <img data-src="./img-loop/img/2.png" alt="懶加載2" />
  <img data-src="./img-loop/img/3.jpg" alt="懶加載3" />
  <img data-src="./img-loop/img/4.jpg" alt="懶加載4" />
  <img data-src="./img-loop/img/5.jpg" alt="懶加載5" />
</body>
</html>
複製代碼
  • 下面編寫js;
const imgs = document.getElementsByTagName('img');
    function lazyLoad(imgs) {
      // 視口的高度;
      const clientH = document.documentElement.clientHeight;
      // 滾動的距離,這裏的邏輯判斷是爲了作兼容性處理;
      const clientT = document.documentElement.scrollTop || document.body.scrollTop;
      for(let i = 0; i < imgs.length; i++) {
        // 邏輯判斷,若是視口高度+滾動距離 > 圖片到瀏覽器頂部的距離就去加載;
        // !imgs[i].src 是避免重複請求,能夠把該條件取消試試:能夠看到不加該條件的話往回滾動就會重複請求;
        if(clientH + clientT > imgs[i].offsetTop && !imgs[i].src) {
          // 使用data-xx的自定義屬性能夠經過dom元素的dataset.xx取得;
          imgs[i].src = imgs[i].dataset.src;
        }
      }
    };
    // 一開始可以加載顯示在視口中的圖片;
    lazyLoad(imgs);
    // 監聽滾動事件,加載後面的圖片;
    window.onscroll = () => lazyLoad(imgs);
複製代碼

至此,咱們就完成了開頭gif圖的懶加載的效果。

5. 性能優化

其實上面的代碼仍是有不少性能優化的地方,好比說對於頻繁觸發的scroll事件會給瀏覽器形成很大的壓力。咱們可使用節流函數作一個優化;

  • 沒有優化前,滾動的時候lazyLoad函數頻繁觸發;

  • 使用節流函數進行優化;
// 設置節流函數
    function throttle(fn, delay) {
      let timer = null;
      return () => {
        if(timer) {
          return;
        };
        timer = setTimeout(() => {
          fn(imgs);
          timer = null;
        }, delay)
      }
    }
    // 監聽滾動事件,加載後面的圖片;
    window.onscroll = throttle(lazyLoad, 500);
複製代碼
  • 優化後的效果;


完整代碼

下一篇:懶加載的第二種實現方式

相關文章
相關標籤/搜索