图片懒加载


theme: fancy

什么是图片懒加载

图片懒加载是一种网页优化技术,它延迟加载页面上的图片资源,直到用户滚动到它们所在的位置时才加载这些图片。

通常情况下,当用户打开网页时,网页中的所有图片资源都会立即加载,这可能会导致页面加载时间变长,特别是当页面上包含大量的图片时。而图片懒加载技术可以解决这个问题,它只加载用户当前可见区域内的图片,而对于在用户视线之外的图片,则不会加载,直到用户滚动页面到这些图片的位置时才开始加载。

懒加载的好处

首先,如果页面没有进行懒加载的情况下,那么打开页面时会同时请求图片。那么如果页面包含大量图片时,这些图片就会在页面加载时同时请求,不仅加载时间会很长,也会因为一下发送过多请求对服务器造成压力,也给浏览器添加了负担。

  1. 减少页面加载时间: 页面中的图片通常是页面加载时间的主要贡献者之一。通过延迟加载页面中的图片资源,只有在用户需要查看图片时才加载,可以显著减少初始页面加载时间,加快页面的显示速度。这对于提高网页的整体性能和用户体验至关重要。

  2. 节省带宽资源: 对于包含大量图片的页面,提前加载所有图片可能会消耗大量的带宽资源。而图片懒加载只加载用户视线内的图片,可以大大减少页面加载时所需的带宽资源。这对于移动设备或者网络环境较差的用户尤其重要,可以减少因页面加载而消耗的流量。

  3. 改善用户体验: 减少页面加载时间和节省带宽资源可以显著改善用户体验。用户会更快地看到页面内容,减少等待时间。

实现原理

我们知道,如果在标签的src属性里放上图片的url,那么当加载页面时,图片则会进行网络请求,我们想要实现懒加载,首先需要将标签的src属性赋值为空,并且将图片的在线地址url存入人为添加的data-original属性中。这样,当加载页面时,浏览器发现src为空时,就请求不到图片。


  
  
  Document
  
    .img-item{
      display: block;
      height: 300px;
      margin-top: 50px;
    }
  
<img class="img-item" src="" data-original="https://th.bing.com/th?id=ORMS.5053ecdbef05fa7726aa489d27b52e40&amp;pid=Wdp&amp;w=612&amp;h=304&amp;qlt=90&amp;c=1&amp;rs=1&amp;dpr=1.25&amp;p=0" alt="">
<img class="img-item" src="" data-original="https://th.bing.com/th?id=ORMS.c5db2c88af1a76f18d0efe02fcded91d&amp;pid=Wdp&amp;w=612&amp;h=304&amp;qlt=90&amp;c=1&amp;rs=1&amp;dpr=1.25&amp;p=0" alt="">
<img class="img-item" src="" data-original="https://th.bing.com/th?id=ORMS.c5129de8701c4a933d92cd6bf832b233&amp;pid=Wdp&amp;w=300&amp;h=156&amp;qlt=90&amp;c=1&amp;rs=1&amp;dpr=1.25&amp;p=0" alt="">
<img class="img-item" src="" data-original="https://th.bing.com/th?id=ORMS.afe7f6448d6eba0055cd8ce9ac9fdf62&amp;pid=Wdp&amp;w=300&amp;h=156&amp;qlt=90&amp;c=1&amp;rs=1&amp;dpr=1.25&amp;p=0" alt="">
<img class="img-item" src="" data-original="https://th.bing.com/th?id=ORMS.e168b9c5da30772083104ed0f4ef0ecf&amp;pid=Wdp&amp;w=612&amp;h=304&amp;qlt=90&amp;c=1&amp;rs=1&amp;dpr=1.25&amp;p=0" alt="">
<img class="img-item" src="" data-original="https://th.bing.com/th?id=ORMS.8025ce5a977b3826589022cede69e110&amp;piwd=Wdp&amp;w=300&amp;h=156&amp;qlt=90&amp;c=1&amp;rs=1&amp;dpr=1.25&amp;p=0" alt="">
<img class="img-item" src="" data-original="https://th.bing.com/th?id=ORMS.a58ae29e32e20a27d498eed19528ee3c&amp;pid=Wdp&amp;w=300&amp;h=156&amp;qlt=90&amp;c=1&amp;rs=1&amp;dpr=1.25&amp;p=0" alt="">
<img class="img-item" src="" data-original="https://th.bing.com/th?id=ORMS.2049b527600b31b2cd863a380be59848&amp;pid=Wdp&amp;w=300&amp;h=156&amp;qlt=90&amp;c=1&amp;rs=1&amp;dpr=1.25&amp;p=0" alt="
">
<img class="img-item" src="" data-original="https://th.bing.com/th?id=ORMS.9f51912b8b6c19a9891b380ad526db85&amp;pid=Wdp&amp;w=612&amp;h=304&amp;qlt=90&amp;c=1&amp;rs=1&amp;dpr=1.25&amp;p=0" alt="">
<img class="img-item" src="" data-original="https://th.bing.com/th?id=ORMS.1b6375ea147b5704f9d073a326e1fc2a&amp;pid=Wdp&amp;w=300&amp;h=156&amp;qlt=90&amp;c=1&amp;rs=1&amp;dpr=1.25&amp;p=0" alt="">

小伙伴们可以用试试,当我们在别的属性中写入图片地址时,在浏览器中检查一下是否会发送网络请求。

那图片什么时候能显示出来呢?或者说我们什么时候去加载图片。

当图片进入可视区域内,也就是说图片进入我们屏幕的正中央时,我们将data-original中的url赋值给src属性,这样就会去请求图片。

图片懒加载的核心就是因为所有图片并不是第一时间就需要给用户看到,当用户将图片滚动到可视区域时,才加载图片。

当图片进入到可视区域时进行赋值

img.src = img.dataset.original

如何判断图片进入可视区域

首先我们先通过window.innerHeight动态的获取我们屏幕的大小,它是根据我们屏幕的尺寸来判断的。

然后我们先要知道原生JS的一个方法getBoundingClientRect,它可以获取容器的几何信息。

使用该方法返回一个对象,其中top表示元素上边框到屏幕上边的距离,bottom表示元素下边框到屏幕上边的距离。

如何判断图片进入了可视区域呢?

如果一个图片不在可视区域,那么它的top肯定是大于屏幕的高度的,因为该图片在屏幕的下方。

所以当图片进入到可视区域时,它的top小于屏幕高度,我们就可以认为它进入了可视区域。


  
  
  Document
  
    .img-item{
      display: block;
      height: 300px;
      margin-top: 50px;
    }
  
<img class="img-item" src="" data-original="https://th.bing.com/th?id=ORMS.5053ecdbef05fa7726aa489d27b52e40&amp;pid=Wdp&amp;w=612&amp;h=304&amp;qlt=90&amp;c=1&amp;rs=1&amp;dpr=1.25&amp;p=0" alt="">
<img class="img-item" src="" data-original="https://th.bing.com/th?id=ORMS.c5db2c88af1a76f18d0efe02fcded91d&amp;pid=Wdp&amp;w=612&amp;h=304&amp;qlt=90&amp;c=1&amp;rs=1&amp;dpr=1.25&amp;p=0" alt="">
<img class="img-item" src="" data-original="https://th.bing.com/th?id=ORMS.c5129de8701c4a933d92cd6bf832b233&amp;pid=Wdp&amp;w=300&amp;h=156&amp;qlt=90&amp;c=1&amp;rs=1&amp;dpr=1.25&amp;p=0" alt="">
<img class="img-item" src="" data-original="https://th.bing.com/th?id=ORMS.afe7f6448d6eba0055cd8ce9ac9fdf62&amp;pid=Wdp&amp;w=300&amp;h=156&amp;qlt=90&amp;c=1&amp;rs=1&amp;dpr=1.25&amp;p=0" alt="">
<img class="img-item" src="" data-original="https://th.bing.com/th?id=ORMS.e168b9c5da30772083104ed0f4ef0ecf&amp;pid=Wdp&amp;w=612&amp;h=304&amp;qlt=90&amp;c=1&amp;rs=1&amp;dpr=1.25&amp;p=0" alt="">
<img class="img-item" src="" data-original="https://th.bing.com/th?id=ORMS.8025ce5a977b3826589022cede69e110&amp;pid=Wdp&amp;w=300&amp;h=156&amp;qlt=90&amp;c=1&amp;rs=1&amp;dpr=1.25&amp;p=0" alt="">
<img class="img-item" src="" data-original="https://th.bing.com/th?id=ORMS.a58ae29e32e20a27d498eed19528ee3c&amp;pid=Wdp&amp;w=300&amp;h=156&amp;qlt=90&amp;c=1&amp;rs=1&amp;dpr=1.25&amp;p=0" alt="">
<img class="img-item" src="" data-original="https://th.bing.com/th?id=ORMS.2049b527600b31b2cd863a380be59848&amp;pid=Wdp&amp;w=300&amp;h=156&amp;qlt=90&amp;c=1&amp;rs=1&amp;dpr=1.25&amp;p=0" alt="">
<img class="img-item" src="" data-original="https://th.bing.com/th?id=ORMS.9f51912b8b6c19a9891b380ad526db85&amp;pid=Wdp&amp;w=612&amp;h=304&amp;qlt=90&amp;c=1&amp;rs=1&amp;dpr=1.25&amp;p=0" alt="">
<img class="img-item" src="" data-original="https://th.bing.com/th?id=ORMS.1b6375ea147b5704f9d073a326e1fc2a&amp;pid=Wdp&amp;w=300&amp;h=156&amp;qlt=90&amp;c=1&amp;rs=1&amp;dpr=1.25&amp;p=0" alt="">

<script>
    // 判断图片有没有进入可视区域,有的话就将其data-original的值赋给src
    let viewHeight = window.innerHeight
    
    function lazyLoad() {
      let imgs = document.querySelectorAll('img[data-original]')
      imgs.forEach(el => {
        let rect = el.getBoundingClientRect() // 获取容器的几何信息
        if (rect.top < viewHeight) {
          el.src = el.dataset
          el.removeAttribute('data-original')
        }
      })
    }

    lazyLoad()
    document.addEventListener('scroll', lazyLoad)
  </script>

我们通过querySelectorAll去获取具有data-original属性的img标签,它是一个数组。所以它可以使用forEach进行循环,

然后我们在浏览器中绑定一个滚动监听,当我们每次滚动的时候,就会去判断是否有图片进行可视区域内,如果有,就加载图片。

但是有一点要注意的是,为了防止重复去获取已经加载了图片的img标签,加载了的图片我们将它的data-original属性移除。

总结

  1. 将图片的src赋值为空,将图片的地址存储到别的属性中。

  2. 判断图片是否进入可视区域,进入的话再加载图片。


这是一个从 https://juejin.cn/post/7368469208647368723 下的原始话题分离的讨论话题