HOOOS

告别卡顿!用Intersection Observer轻松实现图片懒加载,速度提升不止一点点

0 61 性能优化小能手 Intersection Observer懒加载网页性能优化
Apple

网页加载速度慢,图片太多是元凶之一!特别是那种长长的页面,一堆高清大图,用户还没滚动到,它们就嗷嗷待哺地开始加载,白白浪费流量不说,还卡得人怀疑人生。今天,我就要跟你聊聊如何用Intersection Observer API,这个“黑科技”,优雅地解决图片懒加载问题,让你的网页瞬间起飞!

啥是懒加载?为啥要用它?

懒加载,顾名思义,就是“懒”,不到万不得已(用户要看到了),绝不加载。具体来说,就是让页面上的图片先别急着加载,等到它们进入用户的可视区域(viewport)时,再加载。这样做的好处简直不要太多:

  • 提高加载速度:减少了页面初始加载时需要请求的资源数量,让用户更快地看到内容。
  • 节省流量:避免了用户看不到的图片被加载,节省了用户的流量,特别是对于移动端用户来说,简直是福音。
  • 优化性能:减少了浏览器的资源消耗,提高了页面的响应速度,让用户体验更流畅。

为啥选择Intersection Observer?它比传统方法好在哪?

在Intersection Observer API出现之前,我们通常用以下两种方法来实现懒加载:

  1. 监听scroll事件:通过监听scroll事件,判断图片是否进入可视区域。这种方法简单粗暴,但性能较差,因为scroll事件触发频率太高,容易造成页面卡顿。
  2. 使用setTimeout或requestAnimationFrame:对scroll事件进行节流,减少触发频率。虽然能缓解卡顿问题,但实现起来比较麻烦,而且效果也不一定好。

而Intersection Observer API则完美解决了这些问题。它是一种异步的、高效的API,可以监听目标元素(比如图片)与祖先元素或viewport的交叉状态。简单来说,就是当图片进入或离开可视区域时,它会通知你。相比于传统方法,Intersection Observer具有以下优势:

  • 性能更高:Intersection Observer API使用浏览器原生实现,无需频繁监听scroll事件,性能更高,更省电。
  • 代码更简洁:使用Intersection Observer API,代码更简洁易懂,易于维护。
  • 更加精确:可以设置交叉比例,只有当图片达到一定的可见比例时才加载,更加灵活。

手把手教你用Intersection Observer实现图片懒加载

说了这么多,终于要进入实战环节了。下面,我将一步一步地教你如何使用Intersection Observer API来实现图片懒加载。

1. HTML结构

首先,我们需要在HTML中为图片添加一些特殊的属性。通常,我们会使用data-src属性来存储图片的真实地址,而src属性则留空,或者使用一张占位图。

<img data-src="image1.jpg" src="placeholder.gif" alt="Image 1">
<img data-src="image2.jpg" src="placeholder.gif" alt="Image 2">
<img data-src="image3.jpg" src="placeholder.gif" src="placeholder.gif" alt="Image 3">

注意placeholder.gif是一张占位图,可以是任何你喜欢的图片,只要足够小,不影响加载速度即可。

2. JavaScript代码

接下来,我们需要编写JavaScript代码来使用Intersection Observer API。

// 获取所有需要懒加载的图片
const images = document.querySelectorAll('img[data-src]');

// 创建一个Intersection Observer实例
const observer = new IntersectionObserver((entries, observer) => {
  entries.forEach(entry => {
    // 如果图片进入可视区域
    if (entry.isIntersecting) {
      // 获取图片的真实地址
      const img = entry.target;
      const src = img.dataset.src;

      // 加载图片
      img.src = src;

      // 移除data-src属性,防止重复加载
      img.removeAttribute('data-src');

      // 停止监听该图片
      observer.unobserve(img);
    }
  });
});

// 监听每个图片
images.forEach(img => {
  observer.observe(img);
});

代码解释:

  • document.querySelectorAll('img[data-src]'):获取所有带有data-src属性的<img>元素,也就是我们需要懒加载的图片。
  • new IntersectionObserver((entries, observer) => { ... }):创建一个Intersection Observer实例。它接受一个回调函数作为参数,该回调函数会在目标元素与祖先元素或viewport的交叉状态发生变化时被调用。
    • entries:一个包含所有被监听元素的IntersectionObserverEntry对象的数组。每个IntersectionObserverEntry对象都包含了目标元素的信息,比如是否进入可视区域、交叉比例等。
    • observer:IntersectionObserver实例本身。
  • entry.isIntersecting:判断目标元素是否进入可视区域。如果为true,则表示进入可视区域。
  • img.dataset.src:获取data-src属性的值,也就是图片的真实地址。
  • img.src = src:将图片的真实地址赋值给src属性,触发图片加载。
  • img.removeAttribute('data-src'):移除data-src属性,防止图片被重复加载。
  • observer.unobserve(img):停止监听该图片,因为图片已经加载完成,不再需要监听。
  • images.forEach(img => { observer.observe(img); }):监听每个图片,当图片进入或离开可视区域时,触发回调函数。

3. 更多配置选项

除了上面最基本的用法之外,Intersection Observer API还提供了很多配置选项,可以让你更加灵活地控制懒加载的行为。

  • root:指定根元素。默认情况下,根元素是viewport。你可以将根元素设置为某个容器元素,这样就可以监听图片与该容器的交叉状态。
  • rootMargin:指定根元素的边距。可以用来提前或延迟触发回调函数。
  • threshold:指定交叉比例。可以是一个数字,也可以是一个数组。如果是数字,表示当目标元素与根元素的交叉比例达到该值时,触发回调函数。如果是数组,表示当目标元素与根元素的交叉比例达到数组中的任何一个值时,触发回调函数。

示例:

const options = {
  root: document.querySelector('#container'), // 指定根元素为id为container的元素
  rootMargin: '100px', // 提前100px触发回调函数
  threshold: [0, 0.25, 0.5, 0.75, 1] // 当交叉比例为0, 0.25, 0.5, 0.75, 1时,触发回调函数
};

const observer = new IntersectionObserver((entries, observer) => { ... }, options);

4. 兼容性处理

虽然Intersection Observer API已经得到了广泛的支持,但仍然有一些老版本的浏览器不支持它。为了保证兼容性,我们可以使用polyfill。

  • polyfill:是一种代码,可以为老版本的浏览器提供新的API。

你可以使用以下polyfill来支持Intersection Observer API:

使用方法:

在你的HTML文件中,引入polyfill的JavaScript文件。

<script src="intersection-observer.js"></script>

完整代码示例

为了让你更好地理解,我把完整的代码示例放在下面,你可以直接复制粘贴到你的项目中。

<!DOCTYPE html>
<html>
<head>
  <title>Intersection Observer Lazy Load</title>
  <style>
    .container {
      width: 80%;
      margin: 0 auto;
    }

    img {
      display: block;
      width: 100%;
      margin-bottom: 20px;
    }
  </style>
</head>
<body>
  <div class="container">
    <img data-src="https://via.placeholder.com/800x400?text=Image+1" src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" alt="Image 1">
    <img data-src="https://via.placeholder.com/800x400?text=Image+2" src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" alt="Image 2">
    <img data-src="https://via.placeholder.com/800x400?text=Image+3" src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" alt="Image 3">
    <img data-src="https://via.placeholder.com/800x400?text=Image+4" src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" alt="Image 4">
    <img data-src="https://via.placeholder.com/800x400?text=Image+5" src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" alt="Image 5">
  </div>

  <script>
    // 获取所有需要懒加载的图片
    const images = document.querySelectorAll('img[data-src]');

    // 创建一个Intersection Observer实例
    const observer = new IntersectionObserver((entries, observer) => {
      entries.forEach(entry => {
        // 如果图片进入可视区域
        if (entry.isIntersecting) {
          // 获取图片的真实地址
          const img = entry.target;
          const src = img.dataset.src;

          // 加载图片
          img.src = src;

          // 移除data-src属性,防止重复加载
          img.removeAttribute('data-src');

          // 停止监听该图片
          observer.unobserve(img);
        }
      });
    });

    // 监听每个图片
    images.forEach(img => {
      observer.observe(img);
    });
  </script>
</body>
</html>

总结

使用Intersection Observer API来实现图片懒加载,是一种高效、简洁、优雅的方法。它可以显著提高网页加载速度,节省流量,优化性能,提升用户体验。赶快把这个“黑科技”应用到你的项目中吧!

一些额外的思考

  • 不仅仅是图片:Intersection Observer API不仅仅可以用于图片懒加载,还可以用于其他需要延迟加载的资源,比如视频、iframe等。
  • 结合CDN:将图片资源放到CDN上,可以进一步提高加载速度。
  • 图片优化:对图片进行压缩和优化,可以减少图片的大小,提高加载速度。

希望这篇文章能帮助你更好地理解和使用Intersection Observer API。如果你有任何问题,欢迎在评论区留言,我们一起交流学习! 告别卡顿,拥抱飞速加载的网页吧!

点评评价

captcha
健康