懒加载的新时代:交叉观察器的崭露头角

130 阅读2分钟

交叉观察器(Intersection Observer)是一种浏览器提供的API,用于监测元素与视口(viewport)之间的交叉状态。它可以帮助开发者实现一些常见的功能,如懒加载、无限滚动、可视化数据统计等。

交叉观察器的基本概念是,它可以异步地观察一个或多个元素,当这些元素进入或离开视口时,会触发一个回调函数。通过这个回调函数,开发者可以根据元素与视口的交叉状态来执行相应的操作。

交叉观察器的主要优势在于它提供了一种性能优化的方式。传统的滚动事件监听可能会导致性能问题,因为它需要频繁地检查元素的位置和视口的大小。而交叉观察器则是基于浏览器的内部机制,可以更高效地监测元素的可见性,从而减少了不必要的计算和触发。

使用交叉观察器的步骤通常包括以下几个部分:

  1. 创建一个交叉观察器实例:通过new IntersectionObserver(callback, options)创建一个交叉观察器实例,其中callback是一个回调函数,options是一些配置选项,如阈值(threshold)和根元素(root)等。
  2. 观察目标元素:使用交叉观察器的observe(target)方法来观察一个或多个目标元素。目标元素可以是DOM元素,也可以是CSS选择器字符串。
  3. 处理交叉状态变化:当被观察的元素进入或离开视口时,交叉观察器会触发回调函数,并传递一个entries参数,其中包含了与交叉状态相关的信息,如目标元素、交叉比例、交叉区域的位置等。
  4. 停止观察:如果不再需要观察某个元素,可以使用交叉观察器的unobserve(target)方法来停止观察。

交叉观察器的应用非常广泛。例如,可以利用交叉观察器实现懒加载,只在元素进入视口时才加载图片或其他资源,从而提升页面加载性能。还可以实现无限滚动效果,当滚动到页面底部时自动加载更多内容。此外,交叉观察器还可以用于可视化数据统计,当某个元素进入视口时,触发相应的数据统计操作。

基于IntersectionObserver实现图片懒加载

<!DOCTYPE html>
<html>
  <head>
    <meta charset='utf-8' />
    <title>单张图片懒加载</title>
    <style>
      body {
        height: 300%;
      }
      .lazyImageBox {
        position: absolute;
        width: 300px;
        height: 400px;
        top: 1000px;
        left: 50%;
        transform: translateX(-50%);
        background: url('xxxx.gif') center center #fcfcfc;
      }
      .lazyImageBox img {
        width: 100%;
        height: 100%;
        opacity: 0;
        transition: opacity 2s;
      }
    </style>
  </head>
  <body>
    <div class='lazyImageBox'>
      <img src='' alt='' data-image='xxxxx.png' />
    </div>
    <script>
       
       const singlePageLazy = function singlePageLazy () {
        let url =  lazyImg.getAttribute('data-image');
        lazyImg.src = url;
        lazyImg.onload = function () {
          lazyImg.style.opacity = 1; 
        }
        lazyImg.loaded = true;
      }
      let lazyImageBox = document.querySelector('.lazyImageBox'),
          img = lazyImageBox.querySelector('img'),
          ob = new IntersectionObserver(changes => {
            let item = changes[0];
            const { isIntersecting } = item;
            if(isIntersecting) {
              singlePageLazy();
              ob.unobserve(lazyImageBox);
            }
          }, {threshold : [1]});
      
      ob.observe(lazyImageBox);
    </script>
  </body>  
</html>