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

JavaScript實(shí)現(xiàn)圖片懶加載與預(yù)加載的代碼詳解

 更新時(shí)間:2025年03月11日 08:26:34   作者:六個(gè)點(diǎn)  
圖片懶加載與預(yù)加載是前端優(yōu)化中比較常見的方法,也是前端面試中會(huì)被問到的問題,如果不做懶加載和預(yù)加載,瀏覽器的回流重繪很快,而圖片的加載是需要發(fā)送網(wǎng)絡(luò)請求的,一次性發(fā)很多請求就會(huì)導(dǎo)致網(wǎng)絡(luò)的堵塞,影響用戶體驗(yàn),接下來就讓我們來實(shí)現(xiàn)一下懶加載以及預(yù)加載的效果

引言

圖片懶加載與預(yù)加載是前端優(yōu)化中比較常見的方法,也是前端面試中會(huì)被問到的問題。懶加載就是當(dāng)你打開一個(gè)頁面時(shí),沒有出現(xiàn)在屏幕中的圖片先不加載,等滑到該圖片位置時(shí)再加載,而預(yù)加載就是一次性把圖片加載完。

如果不做懶加載和預(yù)加載,瀏覽器的回流重繪很快,而圖片的加載是需要發(fā)送網(wǎng)絡(luò)請求的,當(dāng)圖片一百甚至一千張時(shí),一次性發(fā)很多請求就會(huì)導(dǎo)致網(wǎng)絡(luò)的堵塞,影響用戶體驗(yàn),接下來就讓我們來實(shí)現(xiàn)一下懶加載以及預(yù)加載的效果。

懶加載

懶加載原理就是監(jiān)聽屏幕滾動(dòng)事件,然后判斷圖片是否出現(xiàn)在屏幕內(nèi),等圖片要出現(xiàn)在屏幕內(nèi)再加載。可以使用js中的getBoundingClientRect()方法,獲取元素的集合屬性,打印如下。

<body>
  <img src="" data-src="https://t7.baidu.com/it/u=1732966997,2981886582&fm=193&f=GIF" alt="">
  <script>
    let img = document.querySelector('img')
    let rect = img.getBoundingClientRect()  // 獲取元素幾何屬性
    console.log(rect);
  </script>
</body>

left:左邊框到窗口左邊的距離,right:右邊框到窗口左邊的距離,bottom:下邊框到窗口上邊的距離,top:上邊框到窗口上邊的距離。

然后判斷圖片是否在容器內(nèi),圖片的top小于窗口的高度,圖片的bottom大于0。

為了讓圖片先不展示,就不能把圖片的url放在src屬性上,于是我們可以在img標(biāo)簽中自己定義一個(gè)屬性data-src,將圖片地址放進(jìn)去,然后當(dāng)圖片要展示時(shí),令圖片的src等于data-src屬性,展示過后的圖片再移除掉data-src屬性。

<img src="" data-src="https://t7.baidu.com/it/u=17329669972981886582&fm=193&f=GIF" alt="">
<script>
    let height = window.innerHeight

    function lazyLoad() {
      const imgs = document.querySelectorAll('[data-src]')
      // console.log(imgs);
      for (let i = 0; i < imgs.length; i++) {
        let rect = imgs[i].getBoundingClientRect() // 獲取元素的集合屬性
        if (rect.bottom > 0 && rect.top < height) {
          imgs[i].src = imgs[i].getAttribute('data-src')

          imgs[i].onload = function () {   // 圖片被瀏覽器加載完畢
            imgs[i].src = imgs[i].getAttribute('src')
          }

          imgs[i].removeAttribute('data-src')
        }
      }
    }

    lazyLoad()

    window.addEventListener('scroll', lazyLoad)
  </script>

當(dāng)然里面的imgs[i].src = imgs[i].getAttribute('data-src')可以換成如下:

// imgs[i].src = imgs[i].getAttribute('data-src')
// imgs[i].onload = function () {     // 圖片被瀏覽器加載完畢
//     imgs[i].src = imgs[i].getAttribute('src')
//  }
 
// 換成

let newImg = new Image()    
newImg.src = imgs[i].getAttribute('data-src')   // 讀取 url
newImg.onload = function () { // 圖片被瀏覽器加載完畢
    imgs[i].src = newImg.getAttribute('src')     
}

目的是為了將圖片的加載過程異步化,以此來減輕主線程的壓力。這是通過創(chuàng)建一個(gè)新的Image對象,然后設(shè)置其src屬性來預(yù)加載圖片,一旦圖片加載完成(onload事件觸發(fā)),再將圖片的src屬性設(shè)置到原來的img元素上。

效果如下:

預(yù)加載

用戶一打開頁面,全部圖片先加載,然后后用戶滑動(dòng)就會(huì)非常地絲滑,但是就會(huì)導(dǎo)致同一時(shí)間加載圖片過多,對服務(wù)器壓力過大。

原理:在加載頁面的同時(shí),創(chuàng)建第二個(gè)線程去加載圖片,當(dāng)圖片加載完畢后,將圖片資源交給第一個(gè)線程去展示,從而實(shí)現(xiàn)圖片的預(yù)加載。

代碼如下;

  <div id="pic"></div>

  <script>
    let pic = document.getElementById('pic')

    let arr = [xxxxx]   // 圖片資源
    // 創(chuàng)建一個(gè)新的線程
    const worker = new Worker('worker.js')
    // 將數(shù)據(jù)發(fā)送給子線程
    worker.postMessage(arr)
  </script>

worker函數(shù)是js自帶的一個(gè)函數(shù),作用就是創(chuàng)建一個(gè)新線程,但是這個(gè)新線程不能操作dom結(jié)構(gòu)。這兩個(gè)線程可以通信,通過postMessage進(jìn)行通訊。

然后worker.js里面去加載圖片,直接通過http請求去加載資源,回來的是blob類型的文件。

// worker.js   self就是worker

self.onmessage = function (e) {
  // console.log(e.data);   // 傳過來的圖片資源
  // 將數(shù)組中的地址資源加載出來
  let arr = e.data;
  for (let i = 0; i < arr.length; i++) {
    let xhr = new XMLHttpRequest();
    xhr.open("get", arr[i], true);
    xhr.responseType = 'blob'  // 文件類型
    xhr.send();
    xhr.onload = function () {
      if (xhr.readyState === 4 && xhr.status === 200) {
        // console.log(xhr.response);
        self.postMessage(xhr.response);   //將圖片發(fā)送給主線程
      }
    }
  }
}

然后主線程去接收資源再進(jìn)行渲染;

<body>
  <div id="pic"></div>

  <script>
    let pic = document.getElementById('pic')

    let arr = [xxxxx]   // 圖片資源
    // 創(chuàng)建一個(gè)新的線程
    const worker = new Worker('worker.js')
    // 將數(shù)據(jù)發(fā)送給子線程
    worker.postMessage(arr)
    // 接收子線程發(fā)送的數(shù)據(jù)
    worker.onmessage = function (e) {
      console.log(e.data);
      const img = new Image()
      // console.log(window.URL.createObjectURL(e.data));
      img.src = window.URL.createObjectURL(e.data)
      pic.appendChild(img)
    }
  </script>
</body>

window.URL.createObjectURL(e.data)是window自帶的方法,作用就是將blob資源轉(zhuǎn)換成url。

小結(jié)

  • 懶加載原理:當(dāng)頁面加載完畢后,判斷在可視區(qū)域內(nèi)的圖片先加載,當(dāng)用戶滾動(dòng)時(shí),判斷圖片是否進(jìn)入可視區(qū)域,如果進(jìn)入可視區(qū),則將圖片的src替換為真實(shí)圖片路徑,從而實(shí)現(xiàn)懶加載的原理。
  • 預(yù)加載原理:在加載頁面的同時(shí),開一個(gè)新線程去加載圖片,當(dāng)圖片加載完畢后,將圖片資源交給主線程去展示,從而實(shí)現(xiàn)圖片的預(yù)加載。

以上就是JavaScript實(shí)現(xiàn)圖片懶加載與預(yù)加載的代碼詳解的詳細(xì)內(nèi)容,更多關(guān)于JavaScript圖片懶加載與預(yù)加載的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • JS可視化學(xué)習(xí)向量計(jì)算點(diǎn)到線段的距離并展示

    JS可視化學(xué)習(xí)向量計(jì)算點(diǎn)到線段的距離并展示

    這篇文章主要為大家介紹了JS可視化學(xué)習(xí)向量計(jì)算點(diǎn)到線段的距離并展示實(shí)例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-12-12
  • 小程序?qū)崿F(xiàn)簡單語音聊天的示例代碼

    小程序?qū)崿F(xiàn)簡單語音聊天的示例代碼

    這篇文章主要介紹了小程序?qū)崿F(xiàn)簡單語音聊天的示例代碼,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-07-07
  • JavaScript實(shí)現(xiàn)圖片輪播的方法

    JavaScript實(shí)現(xiàn)圖片輪播的方法

    這篇文章主要介紹了JavaScript實(shí)現(xiàn)圖片輪播的方法,使用純javascript實(shí)現(xiàn)圖片輪播切換的相關(guān)技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下
    2015-07-07
  • 簡單實(shí)現(xiàn)js拖拽效果

    簡單實(shí)現(xiàn)js拖拽效果

    這篇文章主要教大家如何簡單實(shí)現(xiàn)js拖拽效果,很詳細(xì)的js拖拽效果實(shí)現(xiàn)代碼,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-07-07
  • 三種動(dòng)態(tài)加載js的jquery實(shí)例代碼另附去除js方法

    三種動(dòng)態(tài)加載js的jquery實(shí)例代碼另附去除js方法

    這篇文章主要介紹了三種動(dòng)態(tài)加載js的jquery實(shí)例代碼另附去除js方法,需要的朋友可以參考下
    2014-04-04
  • javascript實(shí)現(xiàn)簡單的鼠標(biāo)拖動(dòng)效果實(shí)例

    javascript實(shí)現(xiàn)簡單的鼠標(biāo)拖動(dòng)效果實(shí)例

    這篇文章主要介紹了javascript實(shí)現(xiàn)簡單的鼠標(biāo)拖動(dòng)效果,實(shí)例分析了javascript鼠標(biāo)拖動(dòng)效果的相關(guān)要點(diǎn)與實(shí)現(xiàn)技巧,非常具有實(shí)用價(jià)值,需要的朋友可以參考下
    2015-04-04
  • js實(shí)現(xiàn)動(dòng)態(tài)添加上傳文件頁面

    js實(shí)現(xiàn)動(dòng)態(tài)添加上傳文件頁面

    這篇文章主要為大家詳細(xì)介紹了js實(shí)現(xiàn)動(dòng)態(tài)添加上傳文件頁面,如何動(dòng)態(tài)創(chuàng)建一個(gè)input標(biāo)簽示例,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2018-10-10
  • JS中獲取數(shù)據(jù)庫中的值的方法

    JS中獲取數(shù)據(jù)庫中的值的方法

    在項(xiàng)目中遇到一個(gè)問題,需要在JS中讀取數(shù)據(jù)庫中的值,然后再把值返回到頁面中,解決方案如下:使用Ajax方法來實(shí)現(xiàn),需要用到ajax.dll(一個(gè)ajax技術(shù)開發(fā)的幫助類庫)。
    2013-07-07
  • JS使用正則表達(dá)式找出最長連續(xù)子串長度

    JS使用正則表達(dá)式找出最長連續(xù)子串長度

    這篇文章主要介紹了js 正則找出最長連續(xù)子串長度的實(shí)現(xiàn)代碼,需要的朋友可以參考下
    2017-10-10
  • JavaScript跳出循環(huán)的常用方法詳解

    JavaScript跳出循環(huán)的常用方法詳解

    這篇文章主要介紹了JavaScript中常用的遍歷數(shù)組的方式以及如何提前退出循環(huán),常用退出循環(huán)的方式包括break、continue、return和throw,文中通過代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2025-03-03

最新評(píng)論