您好,登錄后才能下訂單哦!
這篇文章主要講解了“web前端圖片懶加載的原理與實現方式有哪些”,文中的講解內容簡單清晰,易于學習與理解,下面請大家跟著小編的思路慢慢深入,一起來研究和學習“web前端圖片懶加載的原理與實現方式有哪些”吧!
大型網站如常用的淘寶,京東等頁面,需要展示大量的商品圖片信息,如果打開網頁時讓所有圖片一次性加載完成,需要處理很多次網絡請求,等待加載時間比較長,用戶體驗感很差。
有一種常用的解決方式是:隨著滾動動態加載,即圖片的惰性加載。視圖之外的圖片默認不加載,隨著頁面的滾動,圖片進入了顯示的范圍,則觸發圖片的加載顯示。
優點:頁面加載速度快,用戶體驗感更好且節省流量
1.初始化時,圖片標簽的src不能是真實的圖片地址,也不可以是空地址或者壞地址(會出現圖片加載失敗的圖標)。
2.初始化的時候,可以設置圖片的src是某一個小型圖片。例如一張1px*1px的透明圖片。由于所有圖片都使用這一張圖片,只會發送一次請求,不會增加性能負擔。將圖片的真實路徑綁定給一個自定義屬性,例如data-url。注意:頁面的img元素,如果沒有src屬性,瀏覽器就不會發出請求去下載圖片
<img data-url="xxx" src="1px.gif" width="100" height="100"/>
3.定義滾動事件,判斷元素進入視口,則將src替換為真正的url地址。利用js提取data-url的真實圖片地址賦值給src屬性
圖片懶加載的關鍵在于獲取元素的位置,并判斷其是否出現在視口。故有以下三種方式
滾動監聽+scrollTop+offsetTop+innerHeight
滾動監聽+getBoundingClientRect()
intersectionObserve()
scrollTop:指網頁元素被滾動條卷去的部分。
offsetTop:元素相對父元素的位置
innerHeight:當前瀏覽器窗口的大小。需要注意兼容性問題。
IE8及更早版本以前沒有提供取得瀏覽器窗口大小的屬性,不過提供了API:document.documentElement.clientHeight/clientWidth:返回元素內容及其內邊距所占據的空間大小。
IE6中,上述屬性必須在標準模式才有效,如果是混雜模式,需要通過document.body.clientWidth 和 document.body. clientHeight 取得相同信息。
var pageWidth = window.innerWidth var pageHeight = window.innerHeight; if (typeof pageWidth != "number"){ //pageWidth的值不是數值,說明沒有innerwidth屬性 if (document.compatMode == "CSS1Compat"){ //標準模式 pageWidth = document.documentElement.clientWidth; pageHeight = document.documentElement.clientHeight; } else { //混雜模式 pageWidth = document.body.clientWidth; pageHeight = document.body.clientHeight; } }
三個屬性之間的關系如圖所示,故當scrollTop+innerHeight > offsetTop,即圖片在視口內,否則圖片在可視區域外。
代碼實現
滾動監聽完成圖片懶加載的簡易版本
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <style> * { margin: 0; padding: 0; } img { margin-top:400px; width: 250px; display: block; } </style> </head> <body> <img src="img/1pxImg.png" data-url="img/1.jpg"> <img src="img/1pxImg.png" data-url="img/2.jpg"> <img src="img/1pxImg.png" data-url="img/3.jpg"> <img src="img/1pxImg.png" data-url="img/4.jpg"> <img src="img/1pxImg.png" data-url="img/5.jpg"> <script> var imgs = document.getElementsByTagName('img') scrollFn() // 監聽滾動事件 window.onscroll = scrollFn function scrollFn() { var clietH = window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight; var scrollTop = document.documentElement.scrollTop || window.pageYOffset || document.body.scrollTop; console.log(clietH, scrollTop); Array.from(imgs).forEach((item) =>{ let eleTop = item.offsetTop // console.log(eleTop) let count = scrollTop + clietH - eleTop console.log(count) // 可設置為>100 查看懶加載效果 if (count > 0) { //從data-url中取出真實的圖片地址賦值給scr item.setAttribute('src', item.getAttribute('data-url')) } }) } </script> </body> </html>
Element.getBoundingClientRect()
方法返回元素的大小及其相對于視口的位置。返回一個對象,對象屬性包括top,right
rectObject = object.getBoundingClientRect();
API返回一個對象,即rectObject為一個對象,其包含以下屬性
rectObject.top:元素上邊到視窗上邊的距離;
rectObject.right:元素右邊到視窗左邊的距離;
rectObject.bottom:元素下邊到視窗上邊的距離;
rectObject.left:元素左邊到視窗左邊的距離;
rectObject.width:元素自身的寬度
rectObject.height:元素自身的高度
故當rectObject.top的值處于0-視口高度,則元素處于可視區。即
getBoundingClientRect(ele).top >= 0 && getBoundingClientRect(ele).top <= offsetHeight
代碼實現
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <style> * { margin: 0; padding: 0; } img { margin-top:400px; width: 250px; display: block; } </style> </head> <body> <img src="img/1pxImg.png" data-url="img/1.jpg"> <img src="img/1pxImg.png" data-url="img/2.jpg"> <img src="img/1pxImg.png" data-url="img/3.jpg"> <img src="img/1pxImg.png" data-url="img/4.jpg"> <img src="img/1pxImg.png" data-url="img/5.jpg"> <script> var imgs = document.getElementsByTagName('img') scrollFn() // 監聽滾動事件 window.onscroll = scrollFn function scrollFn() { var clietH = window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight; Array.from(imgs).forEach((item) =>{ let ele = item.getBoundingClientRect() console.log(clietH,ele.top) // 可以設置為ele.top+200 查看懶加載效果 if (ele.top > 0 && ele.top < clietH) { //從data-url中取出真實的圖片地址賦值給scr item.setAttribute('src', item.getAttribute('data-url')) } }) } </script> </body> </html>
新的API,針對元素的可見時間進行監聽。由于可見(visible)的本質是,目標元素與視口產生一個交叉區,所以這個 API 叫做"交叉觀察器"。
var io = new IntersectionObserver(callback, option);
IntersectionObserver
是瀏覽器原生提供的構造函數,接受兩個參數:callback
是可見性變化時的回調函數,option
是配置對象(該參數可選)。
構造函數的返回值是一個觀察器實例。實例的observe
方法可以指定觀察哪個 DOM 節點。
// 開始觀察 io.observe(document.getElementById('example')); // 停止觀察 io.unobserve(element); // 關閉觀察器 io.disconnect();
上面代碼中,observe
的參數是一個 DOM 節點對象。如果要觀察多個節點,就要多次調用這個方法。
io.observe(elementA); io.observe(elementB);
callack參數
目標元素的可見性變化時,就會調用觀察器的回調函數callback
。
一般會觸發兩次:1.目標元素剛剛進入視口(開始可見),2.完全離開視口(開始不可見)。
callback
函數的參數是一個數組,每個成員都是一個IntersectionObserverEntry
對象。
IntersectionObserverEntry 對象
提供目標元素的信息,一共有六個屬性。
time:可見性發生變化的時間,是一個高精度時間戳,單位為毫秒
target:被觀察的目標元素,是一個 DOM 節點對象
rootBounds:根元素的矩形區域的信息,getBoundingClientRect()方法的返回值,如果沒有根元素(即直接相對于視口滾動),則返回null
boundingClientRect:目標元素的矩形區域的信息
intersectionRect:目標元素與視口(或根元素)的交叉區域的信息
intersectionRatio:目標元素的可見比例,即intersectionRect占boundingClientRect的比例,完全可見時為1,完全不可見時小于等于0
所以可以通過判斷intersectionRatio屬性是否處于(0,1)來判斷元素的可見性
代碼實現
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <style> * { margin: 0; padding: 0; } img { margin-top:400px; width: 250px; display: block; } </style> </head> <body> <img src="img/1pxImg.png" data-url="img/1.jpg"> <img src="img/1pxImg.png" data-url="img/2.jpg"> <img src="img/1pxImg.png" data-url="img/3.jpg"> <img src="img/1pxImg.png" data-url="img/4.jpg"> <img src="img/1pxImg.png" data-url="img/5.jpg"> <script> var imgs = document.getElementsByTagName('img') // 觀察器實例 let io = new IntersectionObserver((entires) =>{ entires.forEach(item => { // 原圖片元素 let oImg = item.target if (item.intersectionRatio > 0 && item.intersectionRatio <= 1) { oImg.setAttribute('src', oImg.getAttribute('data-url')) } }) }) // 給每一個圖片設置觀察器 Array.from(imgs).forEach(element => { io.observe(element) }); </script> </body> </html>
感謝各位的閱讀,以上就是“web前端圖片懶加載的原理與實現方式有哪些”的內容了,經過本文的學習后,相信大家對web前端圖片懶加載的原理與實現方式有哪些這一問題有了更深刻的體會,具體使用情況還需要大家實踐驗證。這里是億速云,小編將為大家推送更多相關知識點的文章,歡迎關注!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。