高性能图片懒加载

图片懒加载(Lazy Loading)是一种网页优化技术,当图片需要显示时才加载,避免了不必要的流量消耗和服务器带宽浪费。

当页面包含大量图片时,浏览器会逐一发送 GET 请求获取每张图片的数据流,这会消耗用户的流量和服务器的带宽。无论是在 PC 端还是移动端,屏幕尺寸都是有限的,一次无法显示所有图片。因此,对于那些不在视口中的图片,我们无需立即加载,待用户滚动页面使图片进入可视区域时再进行加载。

基本原理

懒加载的概念非常简单:当页面上的图片进入可视区域时才加载它们。传统的懒加载方法通过监听滚动事件实现,但这种方法性能较差,需要频繁计算滚动位置。Intersection Observer API 则提供了一种更高效的解决方案。

懒加载的实现过程如下:

  1. 给图片设置一个占位图。
html 复制代码
<img src="占位图.png">
  1. 使用 data-src 属性保存真实图片的地址。
html 复制代码
<img src="placeholder.png" data-src="real-image.jpg">
  1. 当图片进入可视区域时,将 data-src 的值赋给 src 属性,从而加载真实图片。

传统方案:监听滚动事件

传统方法通过监听滚动事件来实现懒加载:

javascript 复制代码
window.addEventListener("scroll", () => {
  const imgs = document.querySelectorAll('img');
  imgs.forEach(img => {
    const rect = img.getBoundingClientRect();
    if (rect.top < document.body.clientHeight) {
      img.src = img.dataset.src;
    }
  });
});

这种方法需要频繁计算滚动位置,性能较差,还需使用防抖函数。

新方案:Intersection Observer API

Intersection Observer API 是浏览器原生提供的,用于异步检测目标元素与视口或父元素是否产生交叉。它的优势在于提高性能和简化代码实现。

实现代码

以下是使用 Intersection Observer 实现图片懒加载的完整代码:

javascript 复制代码
let observer = new IntersectionObserver((entries, observer) => {
  entries.forEach(entry => {
    if (entry.isIntersecting) {
      const img = entry.target;
      img.src = img.dataset.src;
      observer.unobserve(img);
    }
  });
}, {
  root: null,
  rootMargin: "0px",
  threshold: 0.1
});

document.querySelectorAll('img').forEach(img => observer.observe(img));

代码解析

  • IntersectionObserver 构造函数接受两个参数:回调函数和配置对象。
  • 回调函数处理所有进入视口的图片,将 data-src 赋值给 src,并取消观察。
  • rootnull 表示视口为根元素。
  • threshold0.1 表示当图片 10% 可见时触发回调。

效果

优势

  1. 高性能:只有在目标元素与视口交叉时才会触发回调。
  2. 简洁:不需要计算滚动距离,代码简洁明了。
  3. 兼容性好:现代浏览器都支持 Intersection Observer。
相关推荐
开开心心就好5 小时前
批量提取PDF中的图片,直接导出原图
前端·javascript·支持向量机·智能手机·pdf·html·启发式算法
默_笙10 小时前
🏛 给 AI 配一间办公室:Harness Engineering 六大模块与它的实现
前端·javascript
linux_cfan11 小时前
videojs v10 源代码系列解读:14 · 谓词守卫:在运行时安全地调用能力
前端·javascript·音视频
天若有情67313 小时前
【纯前端小工具】公历生日转农历,批量查询每年农历生日对应的公历日期(GitHub Pages在线直接用)
前端·javascript·github pages·农历转换·lunisolar·网页小工具
林语琛14 小时前
我写的 switch…break 被 Babel 偷偷吞了
前端·javascript·babel
liuchangng14 小时前
Jev 模型研究:从生成式大模型到决策式模型——System One、RLCD 校准与采用边界
java·javascript·人工智能·python·深度学习
我命由我1234515 小时前
CSS - CSS 媒体查询 orientation
前端·javascript·css·html·css3·html5·js
志尊宝18 小时前
Vue3 零基础每日笔记(048):嵌套路由与命名视图——后台管理系统布局雏形
前端·javascript·vue.js·笔记·html5
@tangguo12319 小时前
npm 和 yarn 配置说明
前端·javascript·npm·node.js·yarn
志尊宝19 小时前
Vue3 零基础每日笔记(052):路由常见坑一次排雷——404、刷新丢参数、部署白屏
前端·javascript·vue.js·笔记·html5