亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

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

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

一. 圖片懶加載的目的

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

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

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

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

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

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

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

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

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

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

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

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

  • scrollTop:指網(wǎng)頁元素被滾動(dòng)條卷去的部分。
  • offsetTop:元素相對(duì)父元素的位置
  • 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; 
 	} 
}
  • 三個(gè)屬性之間的關(guān)系如圖所示,故當(dāng)scrollTop+innerHeight > offsetTop,即圖片在視口內(nèi),否則圖片在可視區(qū)域外。

代碼實(shí)現(xiàn)

滾動(dòng)監(jiā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)聽滾動(dòng)事件
        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中取出真實(shí)的圖片地址賦值給scr
                    item.setAttribute('src', item.getAttribute('data-url')) 
                }
            })
        }
    </script>
</body>
</html>

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

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

rectObject = object.getBoundingClientRect();

API返回一個(gè)對(duì)象,即rectObject為一個(gè)對(duì)象,其包含以下屬性

  • 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

代碼實(shí)現(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)聽滾動(dòng)事件
        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中取出真實(shí)的圖片地址賦值給scr
                    item.setAttribute('src', item.getAttribute('data-url')) 
                }
            })
        }
    </script>
</body>
</html>

3.3 intersectionObserve() intersectionObserve()

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

var io = new IntersectionObserver(callback, option);

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

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

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

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

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

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

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

callack參數(shù)

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

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

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

IntersectionObserverEntry 對(duì)象

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

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

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

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

總結(jié)

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

相關(guān)文章

最新評(píng)論