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

JavaScript優(yōu)化圖片懶加載的性能技巧

 更新時間:2024年06月13日 09:26:34   作者:睡著學  
前端發(fā)展過程中有許多性能優(yōu)化的操作,比如防抖、節(jié)流和圖片懶加載等,在這里我們首先聊聊圖片懶加載操作,我們會經常逛像淘寶和京東等購物平臺,一次性全部加載會導致加載時間長、網絡資源消耗大,所以本文給大家介紹了JavaScript優(yōu)化圖片懶加載的性能技巧

背景

前端發(fā)展過程中有許多性能優(yōu)化的操作,比如防抖、節(jié)流和圖片懶加載等。在這里我們首先聊聊圖片懶加載操作。

在最近的618中,我們會經常逛像淘寶和京東等購物平臺。那你覺得在淘寶頁面中的圖片資源是打開頁面時就一次性全部加載完了呢,還是在你滾輪滾動到的區(qū)域才加載圖片呢。

一次性全部加載會導致加載時間長、網絡資源消耗大、內存占用率高和發(fā)出大量圖片請求給服務器帶來的巨大壓力。

所以采用的是只加載當前可見區(qū)域的圖片,隨著用戶的滾動,當其他圖片進入可見區(qū)域時,再進行加載。這種方法就是圖片的懶加載。這種方式可以有效地提高頁面的響應速度,特別是在圖片數量較多或網絡條件較差的情況下,可以避免頁面加載緩慢或卡頓的現象,提供更好的用戶體驗。

如下圖所示,淘寶頁面剛打開時并不是全部加載的。

大致思路

圖片懶加載布局邏輯:

  • 通過將img標簽的src屬性值都設置為同一個圖片的url,這個圖片需要盡可能小。這樣即可以為后續(xù)要真正加載的圖片占位置,也可以讓頁面布局更快地呈現出來,而不是長時間等待圖片加載導致空白。
  • 將每一個img標簽中真正的圖片url存放在一個數據屬性當中。當需要加載時將該數據屬性內的內容賦值給img標簽的src屬性。

圖片懶加載交互邏輯:

  • 首先通過獲取用戶可視窗口高度、滾輪到最頂端的距離和每個圖片到最頂端的距離。
  • 通過監(jiān)聽器監(jiān)聽滾輪滾動事件觸發(fā)懶加載函數。
  • 但是一開始就出現在可視窗口的圖片需要直接加載,所以需要先運行一次懶加載函數。
  • 在懶加載函數里通過判斷(圖片到最頂端的距離)和(用戶可視窗口高度+滾輪到最頂端的距離)的大小判斷是否需要加載。

編輯代碼

html部分

<img src="https://misc.360buyimg.com/mtd/pc/common/img/blank.png"
     data-src="https://img.36krcdn.com/hsossms/20240612/v2_8ec7812750194dbd831babce8806c626@000000_oswg5522709oswg1792oswg1024_img_png?x-oss-process=image/resize,m_mfit,w_600,h_400,limit_0/crop,w_600,h_400,g_center/format,webp" />
<img src="https://misc.360buyimg.com/mtd/pc/common/img/blank.png"
     data-src="https://img.36krcdn.com/20190808/v2_1565254363234_img_jpg">
<img src="https://misc.360buyimg.com/mtd/pc/common/img/blank.png"
     data-src="https://img.36krcdn.com/20190905/v2_1567641293753_img_png">
<img src="https://misc.360buyimg.com/mtd/pc/common/img/blank.png"
     data-src="https://img.36krcdn.com/20190905/v2_1567640518658_img_png">
<img src="https://misc.360buyimg.com/mtd/pc/common/img/blank.png"
     data-src="https://img.36krcdn.com/20190905/v2_1567642423719_img_000">
<img src="https://misc.360buyimg.com/mtd/pc/common/img/blank.png"
     data-src="https://img.36krcdn.com/20190905/v2_1567642425030_img_000">
<img src="https://misc.360buyimg.com/mtd/pc/common/img/blank.png"
     data-src="https://img.36krcdn.com/20190905/v2_1567642425101_img_000">
<img src="https://misc.360buyimg.com/mtd/pc/common/img/blank.png"
     data-src="https://img.36krcdn.com/20190905/v2_1567642425061_img_000">
<img src="https://misc.360buyimg.com/mtd/pc/common/img/blank.png"
     data-src="https://img.36krcdn.com/20190904/v2_1567591358070_img_jpg">
<img src="https://misc.360buyimg.com/mtd/pc/common/img/blank.png"
     data-src="https://img.36krcdn.com/20190905/v2_1567641974410_img_000">
<img src="https://misc.360buyimg.com/mtd/pc/common/img/blank.png"
     data-src="https://img.36krcdn.com/20190905/v2_1567641974454_img_000">

在html部分中有一個重要的步驟。你會發(fā)現每一個img標簽的src屬性值都是一樣的,我們可以復制鏈接到瀏覽器查看該圖片。

該圖片是中間的小白點:

該圖片的屬性如下:

可以看出這個圖片是非常小的。在頁面打開時,加載的都是這個圖片,真正要加載的圖片url放置在data-src數據屬性里面。最后通過JavaScript部分實現將data-src數據屬性的內容賦值給img標簽的src屬性,然后發(fā)送HTTP請求加載真正的圖片。

css部分

img {
    display: block;
    margin-bottom: 50px;
    width: 400px;
    height: 400px;
}

body {
    background-color: gray;
}

通過設置img 標簽樣式,讓小圖片給真正要放的圖片占位置。

JavaScript部分

  • 變量定義:其中imgs是包含頁面中所有<img>元素的集合,可以通過索引來訪問具體的圖像元素;num表示圖片數量;n記錄被加載的圖片數量。
const imgs = document.getElementsByTagName('img');
const num = imgs.length;
let n = 0
  • 在全局一個設置scroll事件監(jiān)聽器,當事件觸發(fā)后會調用lazyload慢加載函數。
window.addEventListener('scroll', lazyload)
  • 定義一個lazyload慢加載函數:
function lazyload() {
    //可視區(qū)域的高度
    let screenHeight = document.documentElement.clientHeight;
    //滾動條距離最頂部的距離,
    let scrollTop = document.documentElement.scrollTop || document.body.scrollTop;
    //判斷圖片是否存在在可視區(qū)域內
    for (let i = n; i < num; i++) {
        if (imgs[i].offsetTop > scrollTop + screenHeight) {
            break;
        } else {
            //主動觸發(fā)下載
            imgs[i].src = imgs[i].getAttribute('data-src');
            //記錄已經加載過的圖片數量
            n = i + 1;
            if (n === num) {
                //全部加載完畢后移除滾動事件
                window.removeEventListener('scroll', lazyload);
            }
        }
    }
}
  • 首先獲取可視窗口的高度screenHeight、滾動條距離最頂部的距離scrollTop和具體圖片距離最頂端的距離imgs[i].offsetTop。通過for循環(huán)遍歷每個img元素。

    • imgs[i].offsetTop > scrollTop + screenHeight時,也就是說該圖片的區(qū)域并沒有被可視區(qū)域覆蓋過,所以圖片不需要加載,也就沒有別的后續(xù)操作了。
    • 如果imgs[i].offsetTop <= scrollTop + screenHeight時,說明該圖片的區(qū)域被可視區(qū)域覆蓋了,圖片需要進行加載。
  • 當圖片需要加載時,將真正的圖片url賦值給src屬性。由imgs[i].src = imgs[i].getAttribute('data-src')實現。

  • 每次加載一張圖片n的值就加一。當n的值等于num的值時,也就是所有圖片都加載完成后就不需要scroll事件監(jiān)聽器了,所有通過window.removeEventListener('scroll', lazyload)清除監(jiān)聽器。

  • 最后因為首屏內的圖片需要直接加載,而不是通過scroll事件監(jiān)聽器實現加載。所有需要調用一次慢加載函數。

//方法一
document.addEventListener('DOMContentLoaded', lazyload)
//方法二
window.addEventListener('load', lazyload)
  • 方法一通過DOMContentLoaded事件監(jiān)聽器觸發(fā)慢加載函數的速度比方法二通過load事件監(jiān)聽器觸發(fā)慢加載函數的速度快。所以推薦方法一。

節(jié)流優(yōu)化

因為scroll事件監(jiān)聽器在頻繁的滑輪滾動會頻繁觸發(fā)。如果直接在事件處理函數中執(zhí)行大量復雜的操作,可能會導致性能問題。

所以通過使用節(jié)流限制事件觸發(fā)的頻率。

const imgs = document.getElementsByTagName('img');
const num = imgs.length;
//用變量記錄節(jié)流返回的函數
const throttleLazyLoad = throttle(lazyload, 200);
//滾動事件觸發(fā)懶加載
window.addEventListener('scroll', throttleLazyLoad)
let n = 0
//首屏加載,DOMContentLoaded事件是DOM加載完成,不包括圖片(比load事件快)
document.addEventListener('DOMContentLoaded', lazyload)
//首屏加載,load事件是DOM加載完成,包括圖片(比DOMContentLoaded事件慢)
window.addEventListener('load', lazyload)
//懶加載函數
function lazyload(event) {
    //可視區(qū)域的高度
    let screenHeight = document.documentElement.clientHeight;
    //滾動條距離最頂部的距離,
    let scrollTop = document.documentElement.scrollTop || document.body.scrollTop;
    //判斷圖片是否存在在可視區(qū)域內
    for (let i = n; i < num; i++) {
        if (imgs[i].offsetTop > scrollTop + screenHeight) {
            break;
        } else {
            //主動觸發(fā)下載
            imgs[i].src = imgs[i].getAttribute('data-src');
            //記錄已經加載過的圖片數量
            n = i + 1;
            if (n === num) {
                //全部加載完畢后移除滾動事件
                window.removeEventListener('scroll', throttleLazyLoad);
            }
        }
    }
}
//節(jié)流函數
function throttle(func, limit) {
    let inThrottle;
    return function () {
        const context = this;
        const args = arguments;
        if (!inThrottle) {
            func.apply(context, args);
            inThrottle = true;
            setTimeout(() => inThrottle = false, limit);
        }
    };
}

定義了一個節(jié)流函數,它接收要執(zhí)行的函數 func 和時間間隔限制 limit。內部通過一個變量 inThrottle 來標記當前是否處于節(jié)流狀態(tài)。當執(zhí)行返回的函數時,先判斷如果不在節(jié)流狀態(tài),就立即執(zhí)行目標函數,并將 inThrottle 設置為 true,同時使用 setTimeout 在指定時間間隔后將 inThrottle 恢復為 false,從而實現了在規(guī)定時間間隔內只執(zhí)行一次函數的節(jié)流效果,避免了頻繁觸發(fā)導致的性能問題。

再次優(yōu)化

在日常工作時,如果讓你選擇手搓一個節(jié)流函數和直接使用工具庫里的函數,你肯定也會和我一樣偷懶,選擇直接使用工具庫里的現成的函數。

首先在HTML中使用以下代碼引入 Lodash 庫。

<script src="https://cdn.bootcdn.net/ajax/libs/lodash.js/4.17.21/lodash.min.js"></script>

然后可以刪除掉你手搓的節(jié)流函數了,使用 Lodash 庫里的節(jié)流函數。

const imgs = document.getElementsByTagName('img');
const num = imgs.length;
//用變量記錄節(jié)流返回的函數
const throttleLazyLoad = _.throttle(lazyload, 200);//調用Lodash庫里的節(jié)流函數
//滾動事件觸發(fā)懶加載
window.addEventListener('scroll', throttleLazyLoad)
let n = 0
//首屏加載,DOMContentLoaded事件是DOM加載完成,不包括圖片(比load事件快)
document.addEventListener('DOMContentLoaded', lazyload)
//首屏加載,load事件是DOM加載完成,包括圖片(比DOMContentLoaded事件慢)
window.addEventListener('load', lazyload)
//懶加載函數
function lazyload(event) {
    //可視區(qū)域的高度
    let screenHeight = document.documentElement.clientHeight;
    //滾動條距離最頂部的距離,
    let scrollTop = document.documentElement.scrollTop || document.body.scrollTop;
    //判斷圖片是否存在在可視區(qū)域內
    for (let i = n; i < num; i++) {
        if (imgs[i].offsetTop > scrollTop + screenHeight) {
            break;
        } else {
            //主動觸發(fā)下載
            imgs[i].src = imgs[i].getAttribute('data-src');
            //記錄已經加載過的圖片數量
            n = i + 1;
            if (n === num) {
                //全部加載完畢后移除滾動事件
                window.removeEventListener('scroll', throttleLazyLoad);
            }
        }
    }
}

呈現效果

當所有圖片加載完后滾動事件就不會觸發(fā)慢加載函數了,并且也有節(jié)流效果。

首屏的圖片立即加載,區(qū)域圖片在滾動到再加載。

以上就是JavaScript優(yōu)化圖片懶加載的性能技巧的詳細內容,更多關于JavaScript優(yōu)化圖片懶加載的資料請關注腳本之家其它相關文章!

相關文章

  • js自定義鼠標右鍵的實現原理及源碼

    js自定義鼠標右鍵的實現原理及源碼

    這篇文章主要介紹了js自定義鼠標右鍵的實現原理及源碼,需要的朋友可以參考下
    2014-06-06
  • 詳解webpack 多頁面/入口支持&公共組件單獨打包

    詳解webpack 多頁面/入口支持&公共組件單獨打包

    這篇文章主要介紹了詳解webpack 多頁面/入口支持&公共組件單獨打包,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-06-06
  • JavaScript實現簡單獲取當前網頁網址的方法

    JavaScript實現簡單獲取當前網頁網址的方法

    這篇文章主要介紹了JavaScript實現簡單獲取當前網頁網址的方法,通過location對象的href方法來獲取網址,非常簡單實用,需要的朋友可以參考下
    2015-11-11
  • 利用JS實現獲取當前系統電量情況

    利用JS實現獲取當前系統電量情況

    在前端瀏覽器中我們可以通過使用JavaScript的navigator.getBattery()方法來獲取當前系統的電池情況,本文將介紹如何使用這個API以及它在實際應用中的使用,需要的可以參考下
    2023-12-12
  • ES6中Object.assign方法使用詳解

    ES6中Object.assign方法使用詳解

    這篇文章主要給大家介紹了關于ES6中Object.assign方法使用的相關資料,Object.assign可以用來處理數組,但是會把數組視為對象,文中通過代碼介紹的非常詳細,需要的朋友可以參考下
    2024-06-06
  • 利用JS自動打開頁面上鏈接的實現代碼

    利用JS自動打開頁面上鏈接的實現代碼

    今天經過測試,實現了利用JS來自動打開頁面上的鏈接的功能,其實比較簡單,就是在頁面上把鏈接列表列出來,然后通過JQuery的相關控制,在框架頁中把鏈接打開,具體能做什么用,大家自己想,哈哈。
    2011-09-09
  • js實現日期級聯效果

    js實現日期級聯效果

    本篇文章主要是對js實現日期級聯效果的實例進行了介紹,需要的朋友可以過來參考下,希望對大家有所幫助
    2014-01-01
  • 深入了解JavaScript Promise

    深入了解JavaScript Promise

    這篇文章主要為大家介紹了JavaScript Promise,具有一定的參考價值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來幫助
    2021-12-12
  • js實現多張圖片每隔一秒切換一張圖片

    js實現多張圖片每隔一秒切換一張圖片

    這篇文章主要為大家詳細介紹了js實現多張圖片每隔一秒切換一張圖片,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2019-07-07
  • 頁面載入結束自動調用js函數示例

    頁面載入結束自動調用js函數示例

    當頁面加載完成后自動調用預先編好的js函數,在某些特殊情況下還是比較實用的,具體實現如下,感興趣的朋友可以參考下
    2013-09-09

最新評論