前端性能优化之图片懒加载 | 青训营笔记

96 阅读3分钟

图片懒加载(Lazy Loading)也叫延迟加载,表示在页面初始加载(如用户刚打开网页)时,不会一次性的把所有图片资源都进行请求和加载,而是等到图片即将进入浏览器的可视区域时再去动态的加载该图片。这样可以避免加载那些用户可能根本不会看到的图片,从而节省网络带宽、提升页面的初始加载速度和用户体验。

  • 实现原理

通过判断图片元素与浏览器可视区域的位置关系,当图片即将进入可视区域时,触发图片的加载操作,利用元素的位置信息(如offsetTopclientHeight等属性)以及浏览器视口的尺寸信息(如window.innerHeight)来进行位置关系的判断。

  • 实现方式

    1. 原生JS

      • 使用数据属性data-src:将实际的图片地址存储在data-src属性中。如:
       <img data-src="https://img.36krcdn.com/20240905_img_png" >
       <img data-src="https://img.36krcdn.com/20241005_img_png" >
      
      • 监听滚动事件:给页面的scroll事件添加监听器,当页面滚动时,在滚动事件处理函数中遍历所有待懒加载图片,通过计算图片元素距离页面顶部的距离以及浏览器视口的高度等信息,判断图片是否进入可视区域。
      • 对懒加载进行防抖:由于滚动事件太敏感,容易高频触发懒加载函数,可以为该事件添加一个防抖的优化操作,减少事件的触发。
      • 具体代码实现如下:
      //获取页面中所有的img元素及其数量
      const imgs = document.getElementsByTagName('img');
      const num = imgs.length
      //记录当前加载的是第几张图片,从0开始
      let n = 0
      //DOM加载完成后执行loadImage函数
      window.addEventListener("DOMContentLoaded",()=>{
          loadImage();
      })
      function loadImage(){
          let screenHeight = document.documentElement.cilentHeight;
          //获取滚动条的位置,兼容不同浏览器
          let scrollTop = document.documentElement.scrollTop || document.body.scrollTop;
          for(let i=0; i<num; i++){
              //判断图片是否在可视区域内
              if( imgs[i].offsetTop < screenHeight + scrollTop ){
                  imgs[i].src = imgs[i].getAttribute('data-src')
                  //更新加载图片的索引
                  n = i + 1
                  //所有图片加载完成,移除scroll事件的监听器
                  if( n === num ){
                      window.removeEventListener( 'scroll' , throttleLazyLoad );
                  }
              }
          }
      }
      //使用lodash库的throttle对懒加载进行防抖
      const throttleLazyLoad=_.throttle(loadImage, 300)
      //添加scroll事件监听器
      window.addEventListener('scroll', throttleLazyLoad)
      
    2. 新增的getBoundingClientRect方法

      getBoundingClientRect方法返回元素相对于视口的位置,用于判断图片是否进入可视区域,当图片距离视口的距离小于视口高度时,加载该图片。

      function loadImage(){
          //可视区高度
          let  viewHeight = document.body.clientHeight 
          let imgs = document.querySelectorAll("img[data-src]")
          imgs.forEach((item,index)=>{
              if(item.dataset.src === "") return
              //用于获取页面中某个元素的左、上、右和下分别相对浏览器视窗的位置
              let rect = item.getBoundingClientRect()
              if(rect.bottom>=0 && rect.top<viewHeight){
                  item.src = item.dataset.src
                  item.removeAttribute("data-src")
              }
          })
      }
      
    3. Vue或React的懒加载指令

      vue或React项目中,可以自定义指令或使用高阶组件实现懒加载。如Vue的v-lazy用于处理图片的懒加载。

      Vue.directive('lazy', {
        inserted: (el) => {
          const observer = new IntersectionObserver(([entry]) => {
            if (entry.isIntersecting) {
              el.src = el.dataset.src;
              observer.unobserve(el);
            }
          });
          observer.observe(el);
        }
      });
      

      在组件中使用:

      <img v-lazy data-src="example.jpg" alt="Lazy Loaded Image">
      

总结

图片懒加载是一项非常实用的前端性能优化技术,合理运用能在多个方面提升页面的性能和用户体验,但在实际应用中也需要综合考虑各种实现细节和注意事项,以达到最佳的优化效果。