最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

前端性能優(yōu)化之圖片懶加載技術(shù)3種落地實現(xiàn)方案

 更新時間:2026年04月10日 09:54:38   作者:豆芽包  
在JavaScript前端開發(fā)中,圖片預(yù)加載是一種常用的技術(shù),旨在提升用戶體驗,減少頁面加載時的等待時間,這篇文章主要介紹了前端性能優(yōu)化之圖片懶加載技術(shù)3種落地實現(xiàn)方案的相關(guān)資料,需要的朋友可以參考下

前言

在前端性能優(yōu)化體系中,圖片資源往往是頁面加載的“重災(zāi)區(qū)” ——電商列表、資訊長文、相冊類頁面,動輒十幾張甚至上百張圖片,若全量一次性加載,不僅拖慢首屏渲染、搶占帶寬,還會造成大量無效請求。

圖片懶加載作為針對性極強(qiáng)的優(yōu)化手段,核心邏輯是非首屏圖片延遲加載,進(jìn)入可視區(qū)域再請求真實資源,既能大幅降低首屏加載耗時,又能節(jié)省流量、提升頁面流暢度,更是優(yōu)化 LCP、CLS 等 Core Web Vitals 核心指標(biāo)的關(guān)鍵。

本文專注拆解圖片懶加載,從原理、適用場景、3種落地實現(xiàn)方案,到避坑指南、效果驗證

一、先理清:圖片懶加載的核心原理

圖片懶加載沒有復(fù)雜底層邏輯,本質(zhì)是 “阻斷默認(rèn)加載 + 監(jiān)聽可視狀態(tài) + 動態(tài)替換資源” 的閉環(huán)流程,針對瀏覽器默認(rèn)自上而下加載圖片的機(jī)制做優(yōu)化:

  1. 標(biāo)記占位:不直接將圖片真實地址放入 src 屬性(避免默認(rèn)加載),改用 data-src等自定義屬性存儲真實地址,src 填充占位圖(loading圖、純色占位、極小縮略圖);
  2. 監(jiān)聽狀態(tài):監(jiān)聽頁面滾動、元素位置,判斷圖片是否進(jìn)入瀏覽器可視區(qū)域;
  3. 加載資源:滿足可視條件后,將 data-src 中的真實地址賦值給 src,完成圖片加載,同時移除監(jiān)聽避免重復(fù)執(zhí)行。

簡單來說:先用占位圖“糊弄”瀏覽器,等用戶快看到圖片時,再加載真實圖片。

二、圖片懶加載的適用場景

圖片懶加載并非所有場景都適用,精準(zhǔn)落地以下場景,優(yōu)化收益最大化:

  • 長頁面圖片列表:電商商品頁、資訊文章、瀑布流相冊、短視頻封面墻;
  • 非首屏圖片:頁面底部、折疊面板、彈窗內(nèi)的圖片,用戶初始瀏覽不到的資源;
  • 大體積圖片:高清banner、詳情圖、實拍圖,單張體積超過100KB的資源。

禁忌場景:首屏核心圖片(Logo、首屏banner、導(dǎo)航圖標(biāo))嚴(yán)禁懶加載,否則會惡化首屏渲染速度。

三、實戰(zhàn):圖片懶加載3種實現(xiàn)方案(從基礎(chǔ)到進(jìn)階)

針對不同項目兼容性、性能要求,整理3種最常用的圖片懶加載方案,覆蓋原生JS、瀏覽器原生API、HTML原生屬性,按需選擇即可。

方案1:原生JS + 滾動監(jiān)聽 + getBoundingClientRect(兼容老瀏覽器)

這是最基礎(chǔ)、兼容性最強(qiáng)的方案,通過監(jiān)聽 scroll 滾動事件,結(jié)合 getBoundingClientRect() 獲取圖片元素位置,判斷是否進(jìn)入視口,支持 IE 等老舊瀏覽器,適合老項目改造。

核心要點:搭配節(jié)流函數(shù)優(yōu)化scroll 高頻觸發(fā)問題,減少性能損耗。

完整代碼實現(xiàn)

<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
  <title>圖片懶加載-滾動監(jiān)聽版</title>
  <style>
    img {
      width: 100%;
      max-width: 800px;
      /* 固定寬高比,防止布局偏移(CLS) */
      aspect-ratio: 16/9;
      object-fit: cover;
      background: #f5f7fa;
      margin: 20px auto;
      display: block;
    }
  </style>
</head>
<body>
  <!-- 懶加載圖片:data-src存真實地址,src為占位圖 -->
  <img class="lazy-img" data-src="https://picsum.photos/800/450?1" src="loading.svg" alt="懶加載圖片1">
  <img class="lazy-img" data-src="https://picsum.photos/800/450?2" src="loading.svg" alt="懶加載圖片2">
  <img class="lazy-img" data-src="https://picsum.photos/800/450?3" src="loading.svg" alt="懶加載圖片3">
  <img class="lazy-img" data-src="https://picsum.photos/800/450?4" src="loading.svg" alt="懶加載圖片4">
  <script>
    // 1. 獲取所有懶加載圖片
    const lazyImages = document.querySelectorAll('.lazy-img');
    // 2. 節(jié)流函數(shù):控制scroll觸發(fā)頻率,避免頻繁執(zhí)行
    const throttle = (fn, delay = 200) => {
      let timer = null;
      return (...args) => {
        if (!timer) {
          timer = setTimeout(() => {
            fn.apply(this, args);
            timer = null;
          }, delay);
        }
      };
    };
    // 3. 核心:判斷圖片是否進(jìn)入可視區(qū)域
    const lazyLoad = () => {
      lazyImages.forEach((img) => {
        // 獲取圖片相對于視口的位置信息
        const rect = img.getBoundingClientRect();
        // 判定條件:圖片頂部 ≤ 視口高度 且 圖片底部 ≥ 0(進(jìn)入可視區(qū)域)
        const isInView = rect.top <= window.innerHeight && rect.bottom >= 0;
        if (isInView) {
          // 替換真實圖片地址
          img.src = img.dataset.src;
          // 加載失敗兜底圖
          img.onerror = () => { img.src = 'error.svg'; };
          // 移除懶加載類,避免重復(fù)處理
          img.classList.remove('lazy-img');
        }
      });
    };
    // 初始化:加載首屏圖片
    lazyLoad();
    // 監(jiān)聽滾動事件(節(jié)流優(yōu)化)
    window.addEventListener('scroll', throttle(lazyLoad));
    // 監(jiān)聽窗口縮放,適配不同屏幕
    window.addEventListener('resize', throttle(lazyLoad));
  </script>
</body>
</html>

方案優(yōu)缺點

  • ? 優(yōu)點:兼容性拉滿,邏輯簡單,無需依賴第三方庫,易調(diào)試;
  • ? 缺點:scroll 事件觸發(fā)頻率高,即使節(jié)流仍有一定性能損耗,需手動處理邊界場景。

方案2:Intersection Observer API(現(xiàn)代瀏覽器首選)

Intersection Observer 是瀏覽器原生提供的異步交叉觀察器,專門用于監(jiān)聽元素與視口(或父容器)的交叉狀態(tài),無需手動監(jiān)聽滾動事件,由瀏覽器底層優(yōu)化,性能遠(yuǎn)超滾動監(jiān)聽方案,是目前主流的圖片懶加載實現(xiàn)方式。

核心優(yōu)勢:異步執(zhí)行、無性能損耗、支持提前加載、配置靈活。

完整代碼實現(xiàn)

<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
  <title>圖片懶加載-Intersection Observer版</title>
  <style>
    img {
      width: 100%;
      max-width: 800px;
      aspect-ratio: 16/9;
      object-fit: cover;
      background: #f5f7fa;
      margin: 20px auto;
      display: block;
    }
  </style>
</head>
<body>
  <img class="lazy-img" data-src="https://picsum.photos/800/450?1" src="loading.svg" alt="懶加載圖片1">
  <img class="lazy-img" data-src="https://picsum.photos/800/450?2" src="loading.svg" alt="懶加載圖片2">
  <img class="lazy-img" data-src="https://picsum.photos/800/450?3" src="loading.svg" alt="懶加載圖片3">
  <img class="lazy-img" data-src="https://picsum.photos/800/450?4" src="loading.svg" alt="懶加載圖片4">
  <script>
    // 1. 創(chuàng)建觀察器實例
    const imgObserver = new IntersectionObserver((entries, observer) => {
      entries.forEach(entry => {
        // 判斷圖片是否進(jìn)入可視區(qū)域
        if (entry.isIntersecting) {
          const img = entry.target;
          // 加載真實圖片
          img.src = img.dataset.src;
          // 錯誤兜底
          img.onerror = () => { img.src = 'error.svg'; };
          // 取消觀察,避免重復(fù)觸發(fā)
          observer.unobserve(img);
        }
      });
    }, {
      // 配置項:提前10%視口高度觸發(fā),提升用戶體驗
      rootMargin: '10% 0px',
      // 觸發(fā)閾值:0表示元素剛進(jìn)入視口就加載
      threshold: 0
    });
    // 2. 遍歷所有圖片,開啟觀察
    document.querySelectorAll('.lazy-img').forEach(img => {
      imgObserver.observe(img);
    });
  </script>
</body>
</html>

關(guān)鍵配置項解析

  • root:監(jiān)聽的根容器,默認(rèn)是瀏覽器視口,可指定父容器實現(xiàn)局部滾動懶加載;
  • rootMargin:擴(kuò)展觸發(fā)邊界,正值提前加載,負(fù)值延遲加載(例:10% 0px 表示圖片距離視口底部10%高度時就加載);
  • threshold:元素可見比例,取值0-1,0為剛可見就觸發(fā),1為完全可見才觸發(fā)。

方案優(yōu)缺點

  • ? 優(yōu)點:性能極致、代碼簡潔、支持預(yù)加載、無需處理節(jié)流/縮放;
  • ? 缺點:不兼容 IE 瀏覽器,可引入 polyfill 做兼容處理。

方案3:HTML原生loading屬性(極簡零代碼)

現(xiàn)代瀏覽器(Chrome 77+、Firefox 75+、Edge 79+)支持原生 loading="lazy" 屬性,無需編寫任何 JS 代碼,直接在 img 標(biāo)簽添加該屬性,瀏覽器自動實現(xiàn)圖片懶加載,是最簡單、最輕量的方案。

適用場景:新項目、無需兼容老舊瀏覽器、追求極簡開發(fā)的場景。

代碼實現(xiàn)

<!-- 原生懶加載:僅需添加 loading="lazy" -->
<img 
  src="https://picsum.photos/800/450?1" 
  loading="lazy" 
  alt="原生懶加載圖片"
  width="800"
  height="450"
>
<img 
  src="https://picsum.photos/800/450?2" 
  loading="lazy" 
  alt="原生懶加載圖片"
  width="800"
  height="450"
>

注意事項

  • 必須設(shè)置圖片 width 和 height,否則瀏覽器無法判斷布局,可能失效;
  • 首屏圖片不建議使用,瀏覽器可能會強(qiáng)制加載首屏內(nèi)的圖片;
  • 兼容性有限,老舊瀏覽器會忽略該屬性,直接加載圖片(優(yōu)雅降級)。

四、圖片懶加載避坑指南(實戰(zhàn)必看)

實操圖片懶加載時,這幾個坑極易忽略,直接影響用戶體驗和性能指標(biāo):

1. 嚴(yán)防布局偏移(CLS)

這是最常見問題:圖片未加載時無固定占位高度,加載后撐開頁面導(dǎo)致布局抖動,CLS指標(biāo)超標(biāo)。

解決方案:通過 CSS aspect-ratio 固定寬高比,或提前設(shè)置 width/height,預(yù)留圖片空間。

2. 占位圖優(yōu)化

  • 占位圖體積盡量?。ńㄗh<2KB),推薦使用 SVG 占位圖、純色背景或 Base64 縮略圖;
  • 避免使用高清圖做占位,失去懶加載意義。

3. 圖片加載失敗兜底

網(wǎng)絡(luò)異常、圖片地址失效會導(dǎo)致圖片加載失敗,需通過 onerror 事件替換兜底圖,提升體驗。

4. 及時銷毀監(jiān)聽/觀察器

JS 實現(xiàn)的懶加載,圖片加載完成后務(wù)必移除滾動監(jiān)聽、取消 Intersection Observer 觀察,防止內(nèi)存泄漏。

5. 兼容禁用JS場景

部分用戶禁用瀏覽器 JS,會導(dǎo)致圖片無法加載,通過 <noscript> 標(biāo)簽兜底。

<img class="lazy-img" data-src="real.jpg" src="loading.svg" alt="圖片">
<!-- 禁用JS時直接加載真實圖片 -->
<noscript>
  <img src="real.jpg" alt="圖片" width="800" height="450">
</noscript>

五、優(yōu)化效果驗證工具

圖片懶加載落地后,通過以下工具驗證優(yōu)化效果:

  1. Chrome 開發(fā)者工具:打開 Network 面板,篩選 Img,滾動頁面觀察圖片請求是否延遲觸發(fā);
  2. Lighthouse:生成性能報告,查看 LCP(最大內(nèi)容繪制)、CLS(累積布局偏移)指標(biāo)是否優(yōu)化;
  3. Performance 面板:查看首屏加載耗時、頁面渲染幀率是否提升。

六、工程化進(jìn)階:懶加載指令封裝+主流插件實戰(zhàn)

實際項目開發(fā)中,重復(fù)手寫懶加載邏輯效率太低,更推薦封裝復(fù)用指令/Hooks或直接使用成熟插件,適配Vue、React等框架工程化場景,下面附上可直接復(fù)用的封裝代碼和插件用法。

6.1 Vue3 圖片懶加載自定義指令(全局封裝)

基于 Intersection Observer 封裝全局懶加載指令,一鍵復(fù)用,無需重復(fù)寫監(jiān)聽邏輯,適配Vue3項目。

步驟1:創(chuàng)建指令文件(directives/lazyLoad.js)

// 全局圖片懶加載指令
const lazyLoad = {
  mounted(el, binding) {
    // 初始化占位圖
    el.src = 'loading.svg';
    // 創(chuàng)建觀察器
    const observer = new IntersectionObserver((entries) => {
      const [entry] = entries;
      if (entry.isIntersecting) {
        // 加載真實圖片
        el.src = binding.value;
        // 加載失敗兜底
        el.onerror = () => { el.src = 'error.svg'; };
        // 停止觀察
        observer.unobserve(el);
      }
    }, { rootMargin: '10% 0px' });
    // 綁定觀察對象
    observer.observe(el);
    // 存儲觀察器,用于卸載
    el._observer = observer;
  },
  // 指令卸載時銷毀觀察器
  unmounted(el) {
    el._observer?.unobserve(el);
  }
};
export default lazyLoad;

步驟2:全局注冊指令(main.js)

import { createApp } from 'vue';
import App from './App.vue';
import lazyLoad from './directives/lazyLoad';
const app = createApp(App);
// 注冊全局指令 v-lazy
app.directive('lazy', lazyLoad);
app.mount('#app');

步驟3:頁面使用

<!-- 直接使用 v-lazy 指令,傳入真實圖片地址 -->
<img v-lazy="https:/picsum.photos800/450?1" alt="指令懶加載" /

6.2 React 圖片懶加載 Hooks 封裝

封裝自定義Hook,實現(xiàn)React函數(shù)組件復(fù)用,適配React項目。

import { useEffect, useRef } from 'react';
// 自定義懶加載Hook
function useLazyImg() {
  const imgRef = useRef(null);
  useEffect(() => {
    const observer = new IntersectionObserver((entries) => {
      const [entry] = entries;
      if (entry.isIntersecting) {
        const img = entry.target;
        img.src = img.dataset.src;
        img.onerror = () => { img.src = 'error.svg'; };
        observer.unobserve(img);
      }
    }, { rootMargin: '10% 0px' });
    if (imgRef.current) observer.observe(imgRef.current);
    return () => {
      if (imgRef.current) observer.unobserve(imgRef.current);
    };
  }, []);
  return imgRef;
}
// 組件使用
export default function LazyImage({ src, alt }) {
  const imgRef = useLazyImg();
  return (
    <img
      ref={src}
      src="loading.svg"
      alt={alt}
      style={{ width: '100%', aspectRatio: '16/9' }}
    />
  );
}

6.3 主流懶加載插件推薦(開箱即用)

不想手動封裝,可直接使用社區(qū)成熟插件,配置簡單、功能完善。

Vue2/Vue3:vue-lazyload

Vue生態(tài)最常用的圖片懶加載插件,支持占位圖、加載失敗、節(jié)流等功能。

# 安裝
npm install vue-lazyload --save
// 注冊(main.js)
import Vue from 'vue';
import VueLazyload from 'vue-lazyload';
Vue.use(VueLazyload, {
  preLoad: 1.3, // 提前加載比例
  error: 'error.svg', // 失敗圖
  loading: 'loading.svg', // 占位圖
  attempt: 1 // 加載次數(shù)
});
// 頁面使用

React:react-lazy-load-image-component

React專用懶加載組件,支持淡入動畫、占位、響應(yīng)式,適配SSR場景。

# 安裝
npm install react-lazy-load-image-component --save
import { LazyLoadImage } from 'react-lazy-load-image-component';
import 'react-lazy-load-image-component/src/effects/blur.css';
// 使用
function ImageList() {
  return (
    <LazyLoadImage
      src="https://picsum.photos/800/450"
      alt="插件懶加載"
      effect="blur" // 淡入模糊效果
      placeholderSrc="loading.svg" // 占位圖
      width="100%"
    />
  );
}

七、方案選型總結(jié)

  • 原生開發(fā)/老項目:選滾動監(jiān)聽 + getBoundingClientRect 方案;
  • 現(xiàn)代瀏覽器/追求性能:選Intersection Observer API 方案(首選);
  • 極簡開發(fā)/零代碼:選原生 loading="lazy"  屬性;
  • Vue/React工程化:優(yōu)先用自定義指令/Hooks,快速復(fù)用;
  • 快速落地:直接用 vue-lazyload/react-lazy-load-image-component 插件。

到此這篇關(guān)于前端性能優(yōu)化之圖片懶加載技術(shù)3種落地實現(xiàn)方案的文章就介紹到這了,更多相關(guān)前端圖片懶加載技術(shù)內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • BootStrop前端框架入門教程詳解

    BootStrop前端框架入門教程詳解

    Bootstrap 是基于 HTML、CSS、JAVASCRIPT 的,它簡潔靈活,使得 Web 開發(fā)更加快捷。這篇文章主要介紹了BootStrop前端框架入門教程詳,需要的朋友可以參考下
    2016-12-12
  • element 中 el-menu 組件的無限極循環(huán)思路代碼詳解

    element 中 el-menu 組件的無限極循環(huán)思路代碼詳解

    這篇文章主要介紹了element 中 el-menu 組件的無限極循環(huán),本文通過實例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2020-04-04
  • javascript關(guān)于open.window子頁面執(zhí)行完成后刷新父頁面的問題分析

    javascript關(guān)于open.window子頁面執(zhí)行完成后刷新父頁面的問題分析

    這篇文章主要介紹了javascript關(guān)于open.window子頁面執(zhí)行完成后刷新父頁面的問題,實例分析了javascript操作子頁面的執(zhí)行與父頁面的刷新技巧,非常具有實用價值,需要的朋友可以參考下
    2015-04-04
  • 小程序拖動區(qū)域?qū)崿F(xiàn)排序效果

    小程序拖動區(qū)域?qū)崿F(xiàn)排序效果

    這篇文章主要為大家詳細(xì)介紹了小程序拖動區(qū)域?qū)崿F(xiàn)排序效果,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-09-09
  • js實現(xiàn)百度聯(lián)盟中一款不錯的圖片切換效果完整實例

    js實現(xiàn)百度聯(lián)盟中一款不錯的圖片切換效果完整實例

    這篇文章主要介紹了js實現(xiàn)百度聯(lián)盟中一款不錯的圖片切換效果的方法,以完整實例形式分析了javascript操作圖片切換的技巧,需要的朋友可以參考下
    2015-03-03
  • javascript刪除數(shù)組元素的七個方法示例

    javascript刪除數(shù)組元素的七個方法示例

    這篇文章主要給大家介紹了關(guān)于javascript刪除數(shù)組元素的七個方法,文中通過示例代碼介紹的非常詳細(xì),對大家學(xué)習(xí)或者使用javascript具有一定的參考學(xué)習(xí)價值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-09-09
  • 史上最全JavaScript常用的簡寫技巧(推薦)

    史上最全JavaScript常用的簡寫技巧(推薦)

    這篇文章主要介紹了JavaScript常用的簡寫技巧,列舉了20條js中常用的簡寫技巧,具體操作步驟大家可查看下文的詳細(xì)講解,感興趣的小伙伴們可以參考一下
    2017-08-08
  • Javascript的原型和原型鏈你了解嗎

    Javascript的原型和原型鏈你了解嗎

    這篇文章主要為大家詳細(xì)介紹了Javascript的原型和原型鏈,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來幫助
    2022-03-03
  • js實現(xiàn)貪吃蛇小游戲

    js實現(xiàn)貪吃蛇小游戲

    這篇文章主要為大家詳細(xì)介紹了js實現(xiàn)貪吃蛇小游戲,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2019-10-10
  • 超級詳細(xì)的webpack?Plugin講解

    超級詳細(xì)的webpack?Plugin講解

    plugin是插件的意思,通常是用于對某個現(xiàn)有的架構(gòu)進(jìn)行擴(kuò)展,下面這篇文章主要給大家介紹了關(guān)于webpack?Plugin的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2022-04-04

最新評論

平乡县| 达拉特旗| 镇原县| 伊通| 娄底市| 舞钢市| 东丽区| 开化县| 鸡东县| 二手房| 巴楚县| 鸡泽县| 竹溪县| 平和县| 开鲁县| 三河市| 阜城县| 新宁县| 星子县| 浪卡子县| 康定县| 莱州市| 福建省| 揭西县| 宜宾县| 富裕县| 长葛市| 广东省| 丹寨县| 永修县| 长葛市| 舞钢市| 鄱阳县| 新泰市| 临泽县| 安达市| 绥芬河市| 淮滨县| 大庆市| 新巴尔虎右旗| 高清|