深入解析图片懒加载的实现原理

377 阅读3分钟

什么是图片懒加载?

图片懒加载是一种优化技术,指的是在页面初次加载时,延迟加载那些当前视口(viewport)外的图片,只有当用户滚动到这些图片所在的位置时,才进行加载。这种方式可以减少初始页面加载时间,降低服务器负载,并提升用户体验。

图片懒加载的实现原理

图片懒加载的核心原理是通过 JavaScript 或 HTML 属性,延迟加载那些当前视口外的图片。具体实现步骤如下:

  1. 初始加载时不加载图片:在页面初次加载时,不加载视口外的图片,而是使用占位符或空的 src 属性。
  2. 监听滚动事件:通过监听滚动事件,检测用户的滚动位置。
  3. 判断图片是否进入视口:当图片进入视口时,替换占位符或空的 src 属性为实际的图片 URL,触发图片加载。

实现图片懒加载的方法

1. 使用 JavaScript 实现图片懒加载

基本实现

首先,我们可以通过 JavaScript 手动实现图片懒加载。以下是一个基本的实现示例:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>图片懒加载示例</title>
  <style>
    .placeholder {
      width: 100%;
      height: 200px;
      background-color: #f0f0f0;
    }
  </style>
</head>
<body>
  <h1>图片懒加载示例</h1>
  <div class="placeholder" data-src="image1.jpg"></div>
  <div class="placeholder" data-src="image2.jpg"></div>
  <div class="placeholder" data-src="image3.jpg"></div>

  <script>
    document.addEventListener("DOMContentLoaded", function() {
      const lazyImages = document.querySelectorAll(".placeholder");

      const lazyLoad = () => {
        lazyImages.forEach(image => {
          if (image.getBoundingClientRect().top < window.innerHeight && image.getBoundingClientRect().bottom > 0) {
            const src = image.getAttribute("data-src");
            if (src) {
              image.style.backgroundImage = `url(${src})`;
              image.classList.remove("placeholder");
              image.removeAttribute("data-src");
            }
          }
        });
      };

      window.addEventListener("scroll", lazyLoad);
      window.addEventListener("resize", lazyLoad);
      lazyLoad(); // Initial check
    });
  </script>
</body>
</html>

在这个示例中:

  • 我们使用 data-src 属性来存储实际的图片 URL。
  • 在 JavaScript 中,通过 getBoundingClientRect 方法判断图片是否进入视口。
  • 当图片进入视口时,替换 data-src 属性为实际的图片 URL,并移除占位符样式。

优化实现

上述基本实现存在一些性能问题,如频繁触发滚动事件监听器。我们可以通过 IntersectionObserver API 来优化实现:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>图片懒加载示例</title>
  <style>
    .placeholder {
      width: 100%;
      height: 200px;
      background-color: #f0f0f0;
    }
  </style>
</head>
<body>
  <h1>图片懒加载示例</h1>
  <div class="placeholder" data-src="image1.jpg"></div>
  <div class="placeholder" data-src="image2.jpg"></div>
  <div class="placeholder" data-src="image3.jpg"></div>

  <script>
    document.addEventListener("DOMContentLoaded", function() {
      const lazyImages = document.querySelectorAll(".placeholder");

      const observer = new IntersectionObserver((entries, observer) => {
        entries.forEach(entry => {
          if (entry.isIntersecting) {
            const image = entry.target;
            const src = image.getAttribute("data-src");
            if (src) {
              image.style.backgroundImage = `url(${src})`;
              image.classList.remove("placeholder");
              image.removeAttribute("data-src");
              observer.unobserve(image);
            }
          }
        });
      });

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

在这个优化实现中:

  • 我们使用 IntersectionObserver API 来监听图片是否进入视口。
  • 当图片进入视口时,触发回调函数,加载实际的图片 URL,并停止观察该图片。

2. 使用 HTML 属性实现图片懒加载

现代浏览器已经支持通过 HTML 属性实现图片懒加载。我们可以使用 loading="lazy" 属性来实现:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>图片懒加载示例</title>
</head>
<body>
  <h1>图片懒加载示例</h1>
  <img src="image1.jpg" loading="lazy" alt="Image 1">
  <img src="image2.jpg" loading="lazy" alt="Image 2">
  <img src="image3.jpg" loading="lazy" alt="Image 3">
</body>
</html>

在这个示例中:

  • 我们在 img 标签中添加 loading="lazy" 属性,浏览器会自动处理图片懒加载。

3. 使用第三方库实现图片懒加载

除了手动实现图片懒加载,我们还可以使用第三方库来简化实现过程。以下是一些常见的图片懒加载库:

1. LazyLoad.js

LazyLoad.js 是一个轻量级的图片懒加载库,使用非常简单:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>图片懒加载示例</title>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/vanilla-lazyload/17.3.1/lazyload.min.js"></script>
</head>
<body>
  <h1>图片懒加载示例</h1>
  <img class="lazy" data-src="image1.jpg" alt="Image 1">
  <img class="lazy" data-src="image2.jpg" alt="Image 2">
  <img class="lazy" data-src="image3.jpg" alt="Image 3">

  <script>
    document.addEventListener("DOMContentLoaded", function() {
      new LazyLoad({
        elements_selector: ".lazy"
      });
    });
  </script>
</body>
</html>

在这个示例中:

  • 我们引入 LazyLoad.js 库,并在 img 标签中使用 data-src 属性存储实际的图片 URL。
  • 使用 LazyLoad.js 库的 LazyLoad 类来初始化懒加载功能。

2. lozad.js

lozad.js 是另一个轻量级的图片懒加载库,使用方法如下:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>图片懒加载示例</title>
  <script src="https://cdn.jsdelivr.net/npm/lozad@1.14.0/dist/lozad.min.js"></script>
</head>
<body>
  <h1>图片懒加载示例</h1>
  <img class="lozad" data-src="image1.jpg" alt="Image 1">
  <img class="lozad" data-src="image2.jpg" alt="Image 2">
  <img class="lozad" data-src="image3.jpg" alt="Image 3">

  <script>
    document.addEventListener("DOMContentLoaded", function() {
      const observer = lozad();
      observer.observe();
    });
  </script>
</body>
</html>

在这个示例中:

  • 我们引入 lozad.js 库,并在 img 标签中使用 data-src 属性存储实际的图片 URL。
  • 使用 lozad.js 库的 lozad 函数来初始化懒加载功能。

结论

图片懒加载是一种有效的优化技术,可以显著提升页面加载速度和用户体验。通过延迟加载视口外的图片,减少初始页面加载时间,降低服务器负载。本文详细解析了图片懒加载的实现原理,并提供了多种实现方法,包括手动实现、使用 HTML 属性以及使用第三方库。

在实际项目中,开发者可以根据项目需求和浏览器兼容性选择合适的实现方法。无论是手动实现还是使用第三方库,图片懒加载都可以帮助我们打造高性能、高用户体验的 Web 应用。