當咱們碰到長網頁有不少圖片時,咱們會採用先加載出如今視口內的幾張圖片,當滾動條滾動到相應圖片的位置時纔去加載別的圖片。這種延遲加載的方式咱們就稱之爲懶加載。html
假設一個場景:當咱們瀏覽淘寶的時候,頁面須要加載很長時間才能顯示出來,根據3秒鐘定律,此時用戶確定已經失去了耐心。可是使用懶加載就可以大大提高頁面的展示速度,從而提高用戶體驗。git
想象一下,若是一我的須要在短期內作不少事情,那這我的確定壓力會很大。服務器也是同樣的,咱們經過懶加載就減輕了服務器的工做量,讓它有時間緩一緩,再來處理後面的事情。github
前面鋪墊了這麼多,下面重點來了(敲黑板!!!)。api
clientHeight
:瀏覽器視口的高度;scrollTop
:滾動軸滾動的距離;offsetTop
:圖片的頭部距離瀏覽器頂部的高度(注意不是距離視口頂部的高度);咱們實現懶加載的想法是一開始只加載顯示在視口內的圖片,從上圖能夠看出,咱們能夠先只加載前兩張圖片。那麼如何保證圖片不加載出來呢?瀏覽器
能夠經過將圖片的地址保存在
img
元素的自定義屬性上面,當須要加載的時候再將該自定義屬性賦值給該圖片的src
。性能優化
那麼問題來了,何時加載後面的圖片呢?bash
就是在咱們滾動滾動軸的時候,當下一張圖片的頂部立刻要出如今視口的時候去加載下一張圖片。服務器
好啦,如今咱們已經知道該什麼去加載下一張圖片了。那麼接下來是第二個問題:怎麼知道下一張圖片立刻要出如今視口上了呢?dom
就是當圖片距離瀏覽器頂部的高度---即
offsetTop
<=
視口高度clientHeight
+ 滾動條的長度scrollTop
。這是重點!!!明白了這個後面就簡單了函數
最後一個問題,如何獲取offsetTop
、scrollTop
、clientHeight
這三個數值呢?
offsetTop
:直接經過img.offsetTop
就能夠獲取;scrollTop
:經過document.documentElement.scrollTop
獲取;clientHeight
:經過document.documentElement.clientHeight
獲取;
此處主要介紹懶加載,對於上述三個api
不熟悉可自行百度學習。建議先記住他們能夠這麼獲取就行。
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圖的懶加載的效果。
其實上面的代碼仍是有不少性能優化的地方,好比說對於頻繁觸發的
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);
複製代碼