3分鐘搞定圖片懶加載

什麼是圖片懶加載

圖片的懶加載就是在頁面打開的時候,不要一次性所有顯示頁面全部的圖片,而是隻顯示當前視口內的圖片,通常在移動端使用(PC端主要是前端分頁或者後端分頁)。javascript

爲何須要懶加載

對於一個頁面加載速度影響最大的因素之一就是圖片資源,若是一個頁面圖片太多(好比某寶,某東等),整個頁面的圖片大小能夠到達幾百兆,即便在百兆寬帶,所有下載的話,也須要上十秒的時間,這對於用戶耐心的考驗是巨大的,更別說網絡差的地方了。css

所以,懶加載是必需要作的,對於頁面未在可視區域內顯示的圖片先不作加載處理,只加載第一映入眼簾的圖片,因爲可視區域顯示的圖片少,加載速度就會大大提高,用戶體驗也會更好。html

並且,用戶可能只翻看一兩頁就退出了,剩下未查看的圖片也就不須要加載了。這也至關於節省了帶寬資源。前端

懶加載實現原理

因爲瀏覽器會自動對頁面中的img標籤的src屬性發送請求並下載圖片。所以,經過html5自定義屬性data-xxx先暫存src的值,而後在須要顯示的時候,再將data-xxx的值從新賦值到img的src屬性便可。html5

實現代碼

這裏模擬兩種狀況:java

狀況一

一、前端已經獲取到全部的圖片了,如今須要將這些圖片以懶加載的形式展現。jquery

例子以下:ajax

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>懶加載Demo1</title>
    <style> .box { width: 600px; margin: 0 auto; } img { width: 100%; } </style>
</head>
<body>
    <div class="box">
        <img src="./images/1.jpg" alt="">
        <img src="./images/2.jpg" alt="">
        <img src="./images/3.jpg" alt="">
        <img src="./images/4.jpg" alt="">
        <img src="./images/5.jpg" alt="">
        <img src="./images/6.jpg" alt="">
        <img src="./images/7.jpg" alt="">
        <img src="./images/8.jpg" alt="">
        <img src="./images/9.jpg" alt="">
        <img src="./images/10.jpg" alt="">
    </div>
</body>
</html>
複製代碼

能夠看出,10張圖片是一次性所有加載完的。後端

下面改形成懶加載:api

首先將頁面上的圖片的 src 屬性設爲空字符串,而圖片的真實路徑則設置在data-src屬性中。

當頁面滾動的時候須要去監聽scroll事件,在scroll事件的回調中,判斷咱們的懶加載的圖片判斷是否出如今視口內,若是出如今視口內,則將data-src賦值到src。

如何判斷一個元素是否在視口內呢?

經過getBoundingClientRect()方法來獲取元素的大小以及位置。這個方法返回一個名爲ClientRect的DOMRect對象,包含了top、right、botton、left、width、height這些值。

隨着滾動條的向下滾動,bound.top會愈來愈小,也就是圖片到可視區域頂部的距離愈來愈小,當bound.top <= clientHeight時,圖片的上沿應該是位於可視區域下沿的位置的臨界點,再滾動一點點,圖片就會進入可視區域。

function isInSight(el) {
  const bound = el.getBoundingClientRect();
  const clientHeight = window.innerHeight;
  //若是隻考慮向下滾動加載
  //const clientWidth = window.innerWeight;
  return bound.top <= clientHeight + 100; // 這裏有個+100是爲了提早加載。
}
複製代碼

源代碼

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>懶加載Demo1</title>
    <style> .box { width: 600px; margin: 0 auto; } img { width: 100%; height: 600px; } </style>
</head>
<body>
    <div class="box">
        <img src="" alt="" data-src="./images/1.jpg">
        <img src="" alt="" data-src="./images/2.jpg">
        <img src="" alt="" data-src="./images/3.jpg">
        <img src="" alt="" data-src="./images/4.jpg">
        <img src="" alt="" data-src="./images/5.jpg">
        <img src="" alt="" data-src="./images/6.jpg">
        <img src="" alt="" data-src="./images/7.jpg">
        <img src="" alt="" data-src="./images/8.jpg">
        <img src="" alt="" data-src="./images/9.jpg">
        <img src="" alt="" data-src="./images/10.jpg">
    </div>
</body>
<script src="https://code.jquery.com/jquery-1.11.3.min.js"></script>
<script> $(function () { // 第一次須要先加載一次 lazyLoad(); $(window).scroll(lazyLoad); function isInSight(el) { const bound = el.getBoundingClientRect(); const clientHeight = $(window).height(); // 可視區高度 return bound.top <= clientHeight + 100; // 這裏有個+100是爲了提早加載。 } function lazyLoad() { $.each($('.box img'), (index,item)=>{ if(isInSight(item)) { $(item).attr('src', $(item).attr('data-src')); } }); } }); </script>
</html>
複製代碼

當向下滑動的時候,從Network面板能夠看到,剩下的圖片是一個個加載的。

可能有人疑問爲何第一次加載了4張,而不是3張?

由於我在判斷是否在可視區內加了100 ,return bound.top <= clientHeight + 100; 能夠提早加載一張圖片。

注意:必定要設置圖片的高度。

提示:src的賦值在js原生和jq是不一樣的,混用的話不會生效。

用js原生方法:document.getElementById("imageId").src = "xxxx.jpg"; 用Jquery方法:$("#imageId").attr("src","xxxx.jpg");

而下面的兩種都不會生效: $("#imageId").src = "xxxx.jpg"; document.getElementById("imageId").attr("src","xxxx.jpg");

切記!


狀況二

二、前端從後端獲取圖片進行展現,後端進行分頁。

思路:當頁面滾動的時候須要去監聽scroll事件,在scroll事件的回調中,判斷滾動條是否滾動到最底部,若是是,則將將圖片的 src 屬性設置爲data-src的值。

判斷是否滾動到最底部的方法:滾動條到頂部距離 + 可視頁面高度 >= 當前頁面高度

var seeHeight = document.documentElement.clientHeight; // 可視頁面高度 
var scrollTop = document.documentElement.scrollTop || document.body.scrollTop; // 滾動條到頂部距離
var bodyHeight = document.body.offsetHeight // 當前頁面高度

而後判斷: scrollTop  + seeHeight  >= bodyHeight 
複製代碼

當滾動條到達底部的時候,獲取後端分頁的數據。

這裏使用一個模擬接口來獲取數據: www.apiopen.top/meituApi?pa…

page爲頁碼數,一次返回20條數據。當page=0時,會隨機返回一頁數據,page>=1時會返回相應頁碼的數據。

源代碼:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>懶加載Demo1</title>
    <style> .box { width: 600px; margin: 0 auto; } img { width: 100%; height: 600px; } </style>
</head>
<body>
    <div class="box"></div>
</body>
<script src="https://code.jquery.com/jquery-1.11.3.min.js"></script>
<script> $(function () { let pageNum = 2; // 由於第一頁沒有圖片,我從第二頁開始的 getImage(pageNum); $(window).scroll(lazyLoad); function getImage(pageNum) { $.ajax({ url:'https://www.apiopen.top/meituApi?page='+pageNum, type: 'GET', success(res) { // 遍歷圖片,將圖片加入div中 if(res.code === 200 && res.data) { res.data.forEach((item,index)=>{ $('.box').append(`<img src="${item.url}">`); }); } }, }); } function lazyLoad() { let seeHeight = document.documentElement.clientHeight; let scrollTop = document.documentElement.scrollTop || document.body.scrollTop; let bodyHeight = document.body.offsetHeight; if((Math.ceil(seeHeight + scrollTop) >= bodyHeight)) { // 向上取整的緣由是可能有小數 getImage(++pageNum); } } }); </script>
</html>
複製代碼

當滾動到20張圖的底部的時候,就會發出ajax請求,請求下一頁數據。

至此本文完,有疑問能夠在評論區隨時交流哈。

(啾咪 ^.<)

相關文章
相關標籤/搜索