欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

前端圖片懶加載的原理與3種實現(xiàn)方式舉例

 更新時間:2023年03月01日 11:41:32   作者:hxxfight  
圖片懶加載又稱圖片延時加載、惰性加載,即在用戶需要使用圖片的時候加載,這樣可以減少請求,節(jié)省帶寬,提高頁面加載速度,相對的,也能減少服務(wù)器壓力,下面這篇文章主要給大家介紹了關(guān)于前端圖片懶加載的原理與3種實現(xiàn)方式的相關(guān)資料,需要的朋友可以參考下

一. 圖片懶加載的目的

大型網(wǎng)站如常用的淘寶,京東等頁面,需要展示大量的商品圖片信息,如果打開網(wǎng)頁時讓所有圖片一次性加載完成,需要處理很多次網(wǎng)絡(luò)請求,等待加載時間比較長,用戶體驗感很差。

有一種常用的解決方式是:隨著滾動動態(tài)加載,即圖片的惰性加載。視圖之外的圖片默認(rèn)不加載,隨著頁面的滾動,圖片進入了顯示的范圍,則觸發(fā)圖片的加載顯示。

優(yōu)點:頁面加載速度快,用戶體驗感更好且節(jié)省流量

二. 圖片懶加載的原理方法

1.初始化時,圖片標(biāo)簽的src不能是真實的圖片地址,也不可以是空地址或者壞地址(會出現(xiàn)圖片加載失敗的圖標(biāo))。

2.初始化的時候,可以設(shè)置圖片的src是某一個小型圖片。例如一張1px*1px的透明圖片。由于所有圖片都使用這一張圖片,只會發(fā)送一次請求,不會增加性能負(fù)擔(dān)。將圖片的真實路徑綁定給一個自定義屬性,例如data-url。注意:頁面的img元素,如果沒有src屬性,瀏覽器就不會發(fā)出請求去下載圖片

<img  data-url="xxx" src="1px.gif" width="100" height="100"/>

3.定義滾動事件,判斷元素進入視口,則將src替換為真正的url地址。利用js提取data-url的真實圖片地址賦值給src屬性

三. 圖片懶加載的實現(xiàn)方法

圖片懶加載的關(guān)鍵在于獲取元素的位置,并判斷其是否出現(xiàn)在視口。故有以下三種方式

  • 滾動監(jiān)聽+scrollTop+offsetTop+innerHeight
  • 滾動監(jiān)聽+getBoundingClientRect()
  • intersectionObserve()

3.1 滾動監(jiān)聽+scrollTop+offsetTop+innerHeight

  • scrollTop:指網(wǎng)頁元素被滾動條卷去的部分。
  • offsetTop:元素相對父元素的位置
  • innerHeight:當(dāng)前瀏覽器窗口的大小。需要注意兼容性問題。
    • IE8及更早版本以前沒有提供取得瀏覽器窗口大小的屬性,不過提供了API:document.documentElement.clientHeight/clientWidth:返回元素內(nèi)容及其內(nèi)邊距所占據(jù)的空間大小。
    • IE6中,上述屬性必須在標(biāo)準(zhǔn)模式才有效,如果是混雜模式,需要通過document.body.clientWidth 和 document.body. clientHeight 取得相同信息。
var pageWidth = window.innerWidth
var pageHeight = window.innerHeight;  
if (typeof pageWidth != "number"){  
    //pageWidth的值不是數(shù)值,說明沒有innerwidth屬性
    if (document.compatMode == "CSS1Compat"){ //標(biāo)準(zhǔn)模式	
        pageWidth = document.documentElement.clientWidth; 
 		pageHeight = document.documentElement.clientHeight; 
 	} else { //混雜模式
 		pageWidth = document.body.clientWidth; 
 		pageHeight = document.body.clientHeight; 
 	} 
}
  • 三個屬性之間的關(guān)系如圖所示,故當(dāng)scrollTop+innerHeight > offsetTop,即圖片在視口內(nèi),否則圖片在可視區(qū)域外。

代碼實現(xiàn)

滾動監(jiān)聽完成圖片懶加載的簡易版本

<!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()
        // 監(jiān)聽滾動事件
        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)
                // 可設(shè)置為>100 查看懶加載效果
                if (count > 0) {
                    //從data-url中取出真實的圖片地址賦值給scr
                    item.setAttribute('src', item.getAttribute('data-url')) 
                }
            })
        }
    </script>
</body>
</html>

3.2 滾動監(jiān)聽+getBoundingClientRect() getBoundingClientRect()

Element.getBoundingClientRect() 方法返回元素的大小及其相對于視口的位置。返回一個對象,對象屬性包括top,right

rectObject = object.getBoundingClientRect();

API返回一個對象,即rectObject為一個對象,其包含以下屬性

  • rectObject.top:元素上邊到視窗上邊的距離;
  • rectObject.right:元素右邊到視窗左邊的距離;
  • rectObject.bottom:元素下邊到視窗上邊的距離;
  • rectObject.left:元素左邊到視窗左邊的距離;
  • rectObject.width:元素自身的寬度
  • rectObject.height:元素自身的高度

故當(dāng)rectObject.top的值處于0-視口高度,則元素處于可視區(qū)。即

getBoundingClientRect(ele).top >= 0 && getBoundingClientRect(ele).top <= offsetHeight

代碼實現(xiàn)

<!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()
        // 監(jiān)聽滾動事件
        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)
                // 可以設(shè)置為ele.top+200 查看懶加載效果
                if (ele.top > 0 && ele.top < clietH) {
                    //從data-url中取出真實的圖片地址賦值給scr
                    item.setAttribute('src', item.getAttribute('data-url')) 
                }
            })
        }
    </script>
</body>
</html>

3.3 intersectionObserve() intersectionObserve()

新的API,針對元素的可見時間進行監(jiān)聽。由于可見(visible)的本質(zhì)是,目標(biāo)元素與視口產(chǎn)生一個交叉區(qū),所以這個 API 叫做"交叉觀察器"。

var io = new IntersectionObserver(callback, option);

IntersectionObserver是瀏覽器原生提供的構(gòu)造函數(shù),接受兩個參數(shù):callback是可見性變化時的回調(diào)函數(shù),option是配置對象(該參數(shù)可選)。

構(gòu)造函數(shù)的返回值是一個觀察器實例。實例的observe方法可以指定觀察哪個 DOM 節(jié)點。

// 開始觀察
io.observe(document.getElementById('example'));

// 停止觀察
io.unobserve(element);

// 關(guān)閉觀察器
io.disconnect();

上面代碼中,observe的參數(shù)是一個 DOM 節(jié)點對象。如果要觀察多個節(jié)點,就要多次調(diào)用這個方法。

io.observe(elementA);
io.observe(elementB);

callack參數(shù)

目標(biāo)元素的可見性變化時,就會調(diào)用觀察器的回調(diào)函數(shù)callback。

一般會觸發(fā)兩次:1.目標(biāo)元素剛剛進入視口(開始可見),2.完全離開視口(開始不可見)。

callback函數(shù)的參數(shù)是一個數(shù)組,每個成員都是一個IntersectionObserverEntry對象。

IntersectionObserverEntry 對象

提供目標(biāo)元素的信息,一共有六個屬性。

  • time:可見性發(fā)生變化的時間,是一個高精度時間戳,單位為毫秒
  • target:被觀察的目標(biāo)元素,是一個 DOM 節(jié)點對象
  • rootBounds:根元素的矩形區(qū)域的信息,getBoundingClientRect()方法的返回值,如果沒有根元素(即直接相對于視口滾動),則返回null
  • boundingClientRect:目標(biāo)元素的矩形區(qū)域的信息
  • intersectionRect:目標(biāo)元素與視口(或根元素)的交叉區(qū)域的信息
  • intersectionRatio:目標(biāo)元素的可見比例,即intersectionRect占boundingClientRect的比例,完全可見時為1,完全不可見時小于等于0

所以可以通過判斷intersectionRatio屬性是否處于(0,1)來判斷元素的可見性

代碼實現(xiàn)

<!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'))
                } 
            })
        })
       // 給每一個圖片設(shè)置觀察器
        Array.from(imgs).forEach(element => {
            io.observe(element) 
        });
    </script>
</body>
</html>

總結(jié)

到此這篇關(guān)于前端圖片懶加載的原理與3種實現(xiàn)方式的文章就介紹到這了,更多相關(guān)前端圖片懶加載實現(xiàn)內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評論