为图片使用延迟加载(懒加载)

发布时间:2020-11-13 17:51:30 阅读:9
由于 HTML 作为<img>元素或 CSS 背景图像内联在 HTML 中,因此图像可以出现在网页上。在本文中,你将发现如何延迟加载两种类型的图像。

图像懒加载

最常见的延迟加载候选是<img>元素中使用的图像。对于嵌入式图像,我们提供了三种用于延迟加载的选项,可以将它们组合使用,以实现跨浏览器的最佳兼容性:

  • 使用浏览器级别的延迟加载
  • 使用路口观察器
  • 使用滚动和调整大小事件处理程序

使用浏览器级别的延迟加载

Chrome 和 Firefox 都支持带有该loading属性的延迟加载。此属性可以添加到<img>元素,也可以添加到<iframe>元素。值lazy告诉浏览器立即将图像加载到视口中,并在用户在其附近滚动时获取其他图像。

注意<iframe loading="lazy">当前是非标准的。虽然已在 Chromium 中实施,但尚无规范,一旦使用,将来可能会进行更改。我们建议你不要使用loading属性来延迟加载 iframe,直到该属性成为规范的一部分。

有关浏览 器支持的详细信息,请参见 loading MDN 的浏览器兼容性表的字段 。如果浏览器不支持延迟加载,则该属性将被忽略,并且图像将照常加载。

对于大多数网站,将此属性添加到嵌入式图像中将提高性能,并节省用户加载他们可能永远不会滚动到的图像。如果你有大量图像,并且想要确保不支持延迟加载的浏览器用户受益,则需要将其与下面介绍的一种方法结合使用。

使用视图检查

为了填充<img>元素的延迟加载,我们使用 JavaScript 来检查元素是否在视口中。如果是这样,则会使用指向所需图像内容的 URL 填充其src(有时是srcset)属性。

如果你之前编写过延迟加载代码,则可能已通过使用事件处理程序(例如scroll或)完成了任务resize。尽管这种方法在所有浏览器之间都是最兼容的,但是现代浏览器提供了一种更高效,更高效的方法来通过 Intersection Observer API 来检查元素可见性。

并非所有浏览器都支持 Intersection Observer,特别是 IE11 和更低版本。如果跨浏览器的兼容性至关重要,请确保阅读下一部分,该部分向你展示如何使用性能较低(但兼容性更高!)的滚动和调整事件处理程序大小来延迟加载图像。

与依赖各种事件处理程序的代码相比,Intersection Observer 更易于使用和阅读,因为你只需要注册一个观察者即可观察元素,而不必编写繁琐的元素可见性检测代码。剩下要做的就是决定当元素可见时该怎么做。让我们为延迟加载的<img>元素假定以下基本标记模式:

<img class="lazy" src="placeholder-image.jpg" data-src="image-to-lazy-load-1x.jpg" data-srcset="image-to-lazy-load-2x.jpg 2x, image-to-lazy-load-1x.jpg 1x" alt="I'm an image!"> 

你应该关注此标记的三个相关部分:

  1. class属性,它是什么,你会在 JavaScript 中选择元素。
  2. src属性引用一个占位符图像,该图像将在页面首次加载时出现。
  3. data-srcdata-srcset属性,这是包含一旦元素中视,你会加载图像的 URL 占位符属性。

现在,让我们看看如何使用 JavaScript 的 Intersection Observer 通过这种标记模式来延迟加载图像:

document.addEventListener("DOMContentLoaded", function() {
  var lazyImages = [].slice.call(document.querySelectorAll("img.lazy"));

  if ("IntersectionObserver" in window) {
    let lazyImageObserver = new IntersectionObserver(function(entries, observer) {
      entries.forEach(function(entry) {
        if (entry.isIntersecting) {
          let lazyImage = entry.target;
          lazyImage.src = lazyImage.dataset.src;
          lazyImage.srcset = lazyImage.dataset.srcset;
          lazyImage.classList.remove("lazy");
          lazyImageObserver.unobserve(lazyImage);
        }
      });
    });

    lazyImages.forEach(function(lazyImage) {
      lazyImageObserver.observe(lazyImage);
    });
  } else {
    // Possibly fall back to event handlers here
  }
}); 

在文档DOMContentLoaded事件中,此脚本在 DOM 中查询所有 <img>带有类别的元素lazy。如果 Intersection Observer 可用,请创建一个新的观察器,当img.lazy元素进入视口时运行该观察器。

所有现代浏览器均支持 Intersection Observer。因此,将其用作 polyfillloading="lazy"将确保大多数游客可以使用延迟加载。它在 Internet Explorer 中不可用。如果 Internet Explorer 支持至关重要,请继续阅读。

使用事件处理程序获得 Internet Explorer 支持

虽然应该使用 Intersection Observer 进行延迟加载,但是你的应用程序要求可能对浏览器兼容性至关重要。你可以 填充工具路口观察的支持(这是最简单的),但你也可以使用回落到代码 scrollresize以及可能的 orientationchange 事件处理程序在音乐会 getBoundingClientRect 以确定元素是否在检视。

假设以前的标记模式相同,此 Glitch 示例将getBoundingClientRectscroll事件处理程序中使用以检查img.lazy视口中是否有任何元素。甲setTimeout调用用于延迟处理,和一个active变量包含其用于节流函数调用的处理的状态。由于图像是延迟加载的,因此它们已从 elements 数组中删除。当 elements 数组达到的length0,滚动事件处理程序代码将被删除。

document.addEventListener("DOMContentLoaded", function() {
  let lazyImages = [].slice.call(document.querySelectorAll("img.lazy"));
  let active = false;

  const lazyLoad = function() {
    if (active === false) {
      active = true;

      setTimeout(function() {
        lazyImages.forEach(function(lazyImage) {
          if ((lazyImage.getBoundingClientRect().top <= window.innerHeight && lazyImage.getBoundingClientRect().bottom >= 0) && getComputedStyle(lazyImage).display !== "none") {
            lazyImage.src = lazyImage.dataset.src;
            lazyImage.srcset = lazyImage.dataset.srcset;
            lazyImage.classList.remove("lazy");

            lazyImages = lazyImages.filter(function(image) {
              return image !== lazyImage;
            });

            if (lazyImages.length === 0) {
              document.removeEventListener("scroll", lazyLoad);
              window.removeEventListener("resize", lazyLoad);
              window.removeEventListener("orientationchange", lazyLoad);
            }
          }
        });

        active = false;
      }, 200);
    }
  };

  document.addEventListener("scroll", lazyLoad);
  window.addEventListener("resize", lazyLoad);
  window.addEventListener("orientationchange", lazyLoad);
}); 

尽管此代码几乎可以在任何浏览器中使用,但它仍然存在潜在的性能问题,即使重复setTimeout调用可能很浪费,但重复调用却很浪费。在此示例中,无论视口中是否有图像,都会每 200 毫秒检查一次文档滚动或调整窗口大小。此外,开发人员还需要乏味的工作来跟踪剩下多少元素以进行延迟加载并取消绑定滚动事件处理程序。

简而言之:在可能的情况下,将浏览器级别的延迟加载与后备 Intersection Observer 实现一起使用,并且只有在最大可能的兼容性是关键的应用程序要求时才使用事件处理程序。

背景图片

尽管<img>标记是在网页上使用图像的最常见方式,但是也可以通过 CSSbackground-image 属性(和其他属性)来调用图像 。浏览器级别的延迟加载不适用于 CSS 背景图像,因此,如果要延迟加载背景图像,则需要考虑其他方法。

与不<img>考虑可见性而加载的元素不同,CSS 中的图像加载行为是通过更多的猜测来完成的。当文件和 CSS 对象模型 和渲染树 是建立,浏览器探讨如何 CSS 请求外部资源之前应用于文档。如果浏览器确定涉及外部资源的 CSS 规则不适用于当前构造的文档,则浏览器不会请求该文档。

通过使用 JavaScript 确定元素何时在视口中,然后将一个类应用于该元素,以应用样式调用背景图像,可以将这种推测性行为用于推迟 CSS 中图像的加载。这将导致在需要时而不是在初始加载时下载图像。例如,让我们以包含背景图像的元素为例:

<div class="lazy-background">
  <h1>Here's a hero heading to get your attention!</h1>
  <p>Here's hero copy to convince you to buy a thing!</p>
  <a href="/buy-a-thing">Buy a thing!</a>
</div> 

div.lazy-background元素通常包含一些 CSS 调用的英雄背景图像。但是,在此延迟加载示例中,你可以通过 在视口中添加到元素的类来隔离div.lazy-background元素的background-image属性visible

.lazy-background {
  background-image: url("hero-placeholder.jpg"); /* Placeholder image */
}

.lazy-background.visible {
  background-image: url("hero.jpg"); /* The final image */
} 

从这里开始,使用 JavaScript 检查该元素是否在视口中(使用 Intersection Observer!),然后在visiblediv.lazy-background元素上添加类 ,从而加载图像:

document.addEventListener("DOMContentLoaded", function() {
  var lazyBackgrounds = [].slice.call(document.querySelectorAll(".lazy-background"));

  if ("IntersectionObserver" in window) {
    let lazyBackgroundObserver = new IntersectionObserver(function(entries, observer) {
      entries.forEach(function(entry) {
        if (entry.isIntersecting) {
          entry.target.classList.add("visible");
          lazyBackgroundObserver.unobserve(entry.target);
        }
      });
    });

    lazyBackgrounds.forEach(function(lazyBackground) {
      lazyBackgroundObserver.observe(lazyBackground);
    });
  }
}); 

如前所述,如果你需要 Internet Explorer 支持延迟加载背景图像,则由于该浏览器缺乏支持,因此需要填充 Intersection Observer 代码。

延迟加载库

以下库可用于延迟加载图像。

  • lazysizes 是功能齐全的延迟加载库,可延迟加载图像和 iframe。它使用的模式与此处显示的代码示例非常相似,因为它会自动绑定到元素上的 lazyload<img>,并且需要你在data-src和 / 或data-srcset属性中指定图像 URL ,它们的内容分别交换到src和 / 或srcset属性中。它使用 Intersection Observer(可以填充),并且可以使用许多插件进行扩展以执行诸如延迟加载视频之类的操作。
  • lozad.js 是仅使用 “路口观察器” 的超轻量级选项。因此,它具有很高的性能,但需要先进行填充,然后才能在较旧的浏览器上使用它。
  • yall.js 是一个使用 Intersection Observer 并回退到事件处理程序的库。与 IE11 和主要浏览器兼容。
  • 如果你需要一个特定于 React 的延迟加载库,请考虑 react-lazyload。尽管它不使用 Intersection Observer,但它确实为习惯于使用 React 开发应用程序的用户提供了一种熟悉的延迟加载图像的方法。

我们在微信上24小时期待你的声音
解答:网站优化,网站建设,搜索引擎优化,APP 开发,小程序开发

非常感谢您有耐心的读完这篇文章:"为图片使用延迟加载(懒加载)",此文章仅为提供更多信息供用户参考使用或为学习交流的方便。如果对您有帮助,请收藏我们的网址:https://www.91webs.cn


18617670560