一. 為什么需要圖片懶加載瞳别?
- 每一張圖片都需要一個(gè)http請(qǐng)求獲取src,如果首頁(yè)有大量圖片壹蔓,加載時(shí)間會(huì)變長(zhǎng)趟妥,用戶體驗(yàn)不好。
二. 懶加載原理佣蓉?有什么好處披摄?
- 用戶其實(shí)不關(guān)心屏幕看不到的地方亲雪,懶加載類似于組件的按需加載,在沒用到的時(shí)候暫時(shí)不請(qǐng)求內(nèi)容疚膊,在需要的時(shí)候再去發(fā)請(qǐng)求义辕。
- 原理:在用戶看不到的時(shí)候使用loading圖占位,真正的圖片內(nèi)容等到圖片處于可視范圍再請(qǐng)求寓盗。
三. 實(shí)現(xiàn)
問題1:如何判斷圖片處于可視范圍终息?
- 兩個(gè)主要API:
Element.getBoundingClientRect():返回元素的大小及其相對(duì)于視口的位置。
window.innerHeight:瀏覽器窗口的視口(viewport)高度(以像素為單位)贞让;如果有水平滾動(dòng)條周崭,也包括滾動(dòng)條高度
- 使用
Element.getBoundingClientRect().top
獲取圖片距離視窗頂部的距離。 - 使用
window.innerHeight
獲取視窗高度喳张。 - 判斷圖片是否在可視范圍续镇,只需要判斷
Element.getBoundingClientRect().top <= window.innerHeight
問題2:圖片的src暫存的是loading圖,如何獲取真正的圖片內(nèi)容销部?
- 自定義
data-src
屬性摸航,用于存放真正的地址,當(dāng)圖片到了可視范圍就使用真正的src替換loading圖舅桩。
問題3:如何動(dòng)態(tài)獲取視窗變化酱虎?
- 監(jiān)聽瀏覽器的滾動(dòng)條事件,觸發(fā)判斷是否加載的回調(diào)擂涛。
問題4:滾動(dòng)時(shí)間觸發(fā)太頻繁读串,如何優(yōu)化,減少重復(fù)判斷撒妈?
- 對(duì)判斷方法進(jìn)行函數(shù)防抖恢暖。
問題5:已經(jīng)加載過的圖片怎么區(qū)分?(避免重復(fù)加載)
- 將已經(jīng)加載過的圖片從圖片列表中刪除狰右。
完整代碼
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
<style>
.container{
width:400px;
}
img{
width:400px;
height:600px;
}
</style>
</head>
<body>
<div class="container">
<img src="./loading.gif" data-src="./smile.jpg" class="lazy">
<img src="./loading.gif" data-src="./smile.jpg" class="lazy">
<img src="./loading.gif" data-src="./smile.jpg" class="lazy">
<img src="./loading.gif" data-src="./smile.jpg" class="lazy">
<img src="./loading.gif" data-src="./smile.jpg" class="lazy">
<img src="./loading.gif" data-src="./smile.jpg" class="lazy">
<img src="./loading.gif" data-src="./smile.jpg" class="lazy">
<img src="./loading.gif" data-src="./smile.jpg" class="lazy">
<img src="./loading.gif" data-src="./smile.jpg" class="lazy">
<img src="./loading.gif" data-src="./smile.jpg" class="lazy">
<img src="./loading.gif" data-src="./smile.jpg" class="lazy">
<img src="./loading.gif" data-src="./smile.jpg" class="lazy">
<img src="./loading.gif" data-src="./smile.jpg" class="lazy">
</div>
<script>
class LazyLoad{
constructor(className){
this.imgList = [...document.querySelectorAll(className)];
this.judge();
this.bindEvent();
}
// 防抖函數(shù)
debounce(fn,delay){
let timer = null;
return function(){
if(timer){
clearTimeout(timer);
}
timer = setTimeout(fn,delay);
}
}
// 監(jiān)聽滾動(dòng)條
bindEvent(){
window.addEventListener('scroll',this.debounce(()=>{
this.imgList.length && this.judge();
},200))
}
// 判斷是否在可視范圍
judge(){
let imgs = this.imgList;
for(let i = 0;i < imgs.length;i++){
if(imgs[i].getBoundingClientRect().top <= window.innerHeight){
this.load(imgs[i],i);
}
}
}
// 將loading圖替換為真實(shí)地址杰捂,加載圖片
load(el,index){
let src = el.getAttribute('data-src');
el.src = src;
this.imgList.splice(index,1);
}
}
const lazy = new LazyLoad('.lazy')
</script>
</body>
</html>
-
只需要給需要懶加載的圖片加上lazy樣式即可。