图片懒加载的实现

图片懒加载是一种优化网页性能的技术,它可以延迟加载图片,直到图片进入浏览器的可视区域,从而减少初始加载时的资源消耗,提升页面加载速度。

  • 加载时机data-src 本身不会触发资源的加载,它只是一个数据存储的地方。只有当通过 JavaScript 等方式将 data-src 的值赋给 src 属性时,浏览器才会发起对该资源的请求。
  • src 是标准的 HTML 属性,用于指定资源的来源地址,浏览器会立即加载该资源。
  • data-src 是自定义属性,用于存储自定义数据。

IntersectionObserver

IntersectionObserver 是浏览器提供的一个用于异步观察目标元素与其祖先元素或顶级文档视口(viewport)交叉状态的 API。它在处理懒加载、无限滚动、广告曝光监测等场景中非常有用,下面从几个方面详细介绍它。

基本原理

IntersectionObserver 允许你注册一个回调函数,当目标元素与指定的根元素(默认为浏览器视口)的交集区域发生变化时,这个回调函数会被触发。它采用了一种非阻塞的异步方式,避免了传统通过监听 scrollresize 等事件进行元素可见性检测时可能带来的性能问题。

基本用法

使用 IntersectionObserver 主要有以下几个步骤:

1. 创建 IntersectionObserver 实例

javascript

ini 复制代码
const observer = new IntersectionObserver(callback, options);
  • callback:当目标元素的可见性发生变化时会调用的回调函数,该函数接收两个参数:

    • entries:一个包含所有被观察元素的 IntersectionObserverEntry 对象的数组,每个 IntersectionObserverEntry 对象描述了一个被观察元素的可见性变化信息。
    • observer:当前的 IntersectionObserver 实例。
  • options:一个可选的配置对象,包含以下属性:

    • root:指定根元素,即用于检查目标元素可见性的元素,默认为浏览器视口。
    • rootMargin:根元素的外边距,类似于 CSS 的 margin 属性,用于扩展或缩小根元素的边界框,格式为 "10px 20px 30px 40px"
    • threshold:一个数值或数值数组,定义了一个或多个交叉比例阈值,当目标元素与根元素的交叉比例达到这些阈值时,回调函数会被触发。例如,[0, 0.5, 1] 表示当目标元素的可见比例为 0%、50%、100% 时都会触发回调。
2. 观察目标元素
ini 复制代码
const target = document.getElementById('target-element');
observer.observe(target);

通过 observe 方法可以让 IntersectionObserver 开始观察指定的目标元素。

3. 停止观察目标元素
ini 复制代码
observer.unobserve(target);

使用 unobserve 方法可以停止对某个目标元素的观察。

原生 JavaScript 实现

通过监听窗口滚动事件和 IntersectionObserver API 来实现图片懒加载。

  1. HTML 部分 :为需要懒加载的图片添加 lazyload 类,并将真实的图片地址存储在 data-src 属性中,src 属性设置为一个占位图片(这里使用了一个透明的 GIF 图片)。

  2. JavaScript 部分

    • IntersectionObserver :如果浏览器支持 IntersectionObserver,则使用它来监听图片是否进入可视区域。当图片进入可视区域时,将 data-src 的值赋给 src 属性,并停止观察该图片。
    • 降级处理 :如果浏览器不支持 IntersectionObserver,则监听 scrollresizeorientationChange 事件,在事件触发时检查图片是否进入可视区域
xml 复制代码
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>IntersectionObserver 图片懒加载示例</title>
</head>

<body>
    <img class="lazy" data-src="https://picsum.photos/200/300" src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" alt="Lazy Loaded Image">
    <img class="lazy" data-src="https://picsum.photos/200/300?random=2" src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" alt="Lazy Loaded Image">

    <script>
        const lazyImages = document.querySelectorAll('img.lazy');

        const observer = new IntersectionObserver((entries, observer) => {
            entries.forEach((entry) => {
                if (entry.isIntersecting) {
                    const img = entry.target;
                    img.src = img.dataset.src;
                    img.classList.remove('lazy');
                    observer.unobserve(img);
                }
            });
        });

        lazyImages.forEach((image) => {
            observer.observe(image);
        });
    </script>
</body>

</html>

代码解释

  • 首先,获取所有带有 lazy 类的图片元素。
  • 然后,创建一个 IntersectionObserver 实例,当目标元素进入视口(isIntersectingtrue)时,将 data-src 属性的值赋给 src 属性,移除 lazy 类,并停止对该元素的观察。
  • 最后,对每个图片元素调用 observe 方法,开始观察它们的可见性变化。

兼容性

IntersectionObserver 已经得到了大多数现代浏览器的支持,但在一些旧版本的浏览器中可能不支持。在使用时,可以结合一些兼容性处理,例如使用 IntersectionObserver 进行懒加载,同时为不支持的浏览器提供降级方案(如监听 scroll 事件)。

相关推荐
前端老宋Running6 分钟前
一次从“卡顿地狱”到“丝般顺滑”的 React 搜索优化实战
前端·react.js·掘金日报
隔壁的大叔6 分钟前
如何自己构建一个Markdown增量渲染器
前端·javascript
用户4445543654268 分钟前
Android的自定义View
前端
WILLF9 分钟前
HTML iframe 标签
前端·javascript
枫,为落叶26 分钟前
Axios使用教程(一)
前端
小章鱼学前端31 分钟前
2025 年最新 Fabric.js 实战:一个完整可上线的图片选区标注组件(含全部源码).
前端·vue.js
ohyeah32 分钟前
JavaScript 词法作用域、作用域链与闭包:从代码看机制
前端·javascript
流星稍逝34 分钟前
手搓一个简简单单进度条
前端
倚栏听风雨1 小时前
详解 TypeScript 中,async 和 await
前端
小皮虾1 小时前
告别服务器!小程序纯前端“图片转 PDF”工具,隐私安全又高效
前端·javascript·微信小程序