在項目開發中,我們往往會遇到一個頁面需要載入很多圖片的情況。我們可以一次性載入全部的圖片,但是考慮到用戶有可能只瀏覽部分圖片。所以我們需要對圖片載入進行優化,只載入瀏覽器視窗內的圖片,當用戶滾動時,再載入更多的圖片。這種載入圖片的方式叫做圖片懶載入,又叫做按需載入或圖片的延時載入。這樣做的好處是:1 ...
在項目開發中,我們往往會遇到一個頁面需要載入很多圖片的情況。我們可以一次性載入全部的圖片,但是考慮到用戶有可能只瀏覽部分圖片。所以我們需要對圖片載入進行優化,只載入瀏覽器視窗內的圖片,當用戶滾動時,再載入更多的圖片。這種載入圖片的方式叫做圖片懶載入,又叫做按需載入或圖片的延時載入。這樣做的好處是:1.可以加快頁面首屏渲染的速度;2.節約用戶的流量。
一.實現思路
1.圖片img標簽自定義一個屬性data-src來存放真實的地址。
2.當滾動頁面時,檢查所有的img標簽,判斷是否出現在事業中,如果出現在視野中,繼續進行判斷,看齊是否被載入過了,如果沒有載入,那就進行載入。
判斷圖片元素是否處於瀏覽器視野中的示意圖(手繪):
二.根據思路完成代碼如下:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>原生js實現圖片懶載入</title> <style> *{ margin: 0; padding: 0; box-sizing: border-box; } ul{ overflow: hidden; list-style: none; } li{ float: left; width: 50%; height: 200px; padding: 10px; } li img{ display: inline-block; width: 100%; height: 100%; } </style> </head> <body> <div class="container"> <ul> <li><img src="http://cdn.jirengu.com/book.jirengu.com/img/1.jpg" alt="" data-src="http://cdn.jirengu.com/book.jirengu.com/img/1.jpg"></li> <li><img src="" alt="" data-src="http://cdn.jirengu.com/book.jirengu.com/img/2.jpg"></li> <li><img src="" alt="" data-src="http://cdn.jirengu.com/book.jirengu.com/img/3.jpg"></li> <li><img src="" alt="" data-src="http://cdn.jirengu.com/book.jirengu.com/img/4.jpg"></li> <li><img src="" alt="" data-src="http://cdn.jirengu.com/book.jirengu.com/img/5.jpg"></li> <li><img src="" alt="" data-src="http://cdn.jirengu.com/book.jirengu.com/img/6.jpg"></li> <li><img src="" alt="" data-src="http://cdn.jirengu.com/book.jirengu.com/img/7.jpg"></li> <li><img src="" alt="" data-src="http://cdn.jirengu.com/book.jirengu.com/img/8.jpg"></li> <li><img src="" alt="" data-src="http://cdn.jirengu.com/book.jirengu.com/img/9.jpg"></li> <li><img src="" alt="" data-src="http://cdn.jirengu.com/book.jirengu.com/img/10.jpg"></li> <li><img src="" alt="" data-src="http://cdn.jirengu.com/book.jirengu.com/img/11.jpg"></li> <li><img src="" alt="" data-src="http://cdn.jirengu.com/book.jirengu.com/img/12.jpg"></li> <li><img src="" alt="" data-src="http://cdn.jirengu.com/book.jirengu.com/img/13.jpg"></li> <li><img src="" alt="" data-src="http://cdn.jirengu.com/book.jirengu.com/img/14.jpg"></li> <li><img src="" alt="" data-src="http://cdn.jirengu.com/book.jirengu.com/img/15.jpg"></li> <li><img src="" alt="" data-src="http://cdn.jirengu.com/book.jirengu.com/img/16.jpg"></li> </ul> </div> <script> // window綁定滾動事件 window.addEventListener('scroll',function(){ // 遍歷所有的img標簽 Array.prototype.slice.apply(document.getElementsByTagName('li')).forEach((li)=>{ let img=li.getElementsByTagName('img')[0]; // 判斷當前img是否出現在了視野中 // 判斷當前img是否被載入過了 if(checkShow(img) && !isLoaded(img)){ loadImg(img); } }) }); // 判斷img是否出現瀏覽器視野中 function checkShow(img) { let scrollTop=document.documentElement.scrollTop; // 頁面向上滾動的高度 let windowHeight=window.innerHeight; //瀏覽器自身高度 let offsetTop=img.offsetTop; //目標標簽相對於document的高度 return (offsetTop > scrollTop && offsetTop <(windowHeight + scrollTop)); } // 判斷是否已經載入過 function isLoaded(img) { return img.getAttribute('src')===img.getAttribute('data-src'); } // 載入圖片 function loadImg(img) { img.setAttribute('src',img.getAttribute('data-src')); } </script> </body> </html>
好了,在瀏覽器中運行一下,第一次進頁面如果不滾動滾輪的話什麼也看不到,所以第一次進頁面需要調用checkShow(),處於視野中的圖片也載入出來。
在代碼最後加上:
// 第一次進頁面載入處於視野中的圖片 Array.prototype.slice.apply(document.getElementsByTagName('li')).forEach((li)=>{ let img=li.getElementsByTagName('img')[0]; // 判斷當前img是否出現在了視野中 // 判斷當前img是否被載入過了 if(checkShow(img) && !isLoaded(img)){ loadImg(img); } })
此時我們發現判斷載入視野中的圖片代碼存在重覆,直接封裝成一個新的方法lazyRenderImg();
// window綁定滾動事件 window.addEventListener('scroll',function(){ // 遍歷所有的img標簽 lazyRenderImg(); }); function lazyRenderImg(){ Array.prototype.slice.apply(document.getElementsByTagName('li')).forEach((li)=>{ let img=li.getElementsByTagName('img')[0]; // 判斷當前img是否出現在了視野中 // 判斷當前img是否被載入過了 if(checkShow(img) && !isLoaded(img)){ loadImg(img); } }) } // 第一次進頁面載入處於視野中的圖片 lazyRenderImg();
三.性能優化
問題:window.scroll 方法頁面只要一滾動就會觸發裡面的方法,對性能影響很大
解決方法:當頁面停止滾動的時候,再去執行頁面中的方法,類似與函數節流(throttle)
Tips:函數節流:等時間間隔執行函數, 讓一個函數不要執行得太頻繁,減少一些過快的調用來節流。
// window綁定滾動事件 let timer; window.addEventListener('scroll',function(){
console.log('scroll') // 遍歷所有的img標簽 if(timer){ clearTimeout(timer) } timer=setTimeout(()=>{
console.log('lazyRenderImg...'); lazyRenderImg(); },300);
通過列印的日誌發現當滾動停止後才執行lazyRenderImg方法的,確實減少了不必要調用lazyRenderImg的次數。
頁面性能優化之圖片懶載入就寫這麼多了,網頁優化還有很多方法與技巧,前端路漫漫其修遠兮,吾將上下而求索。本文不足之處,請多指正。
參考資料:
https://www.jianshu.com/p/1b32e16ed0e5