懒加载实现原理

551 阅读3分钟

什么是懒加载以及好处

  1.懒加载也叫做延迟加载、按需加载,指的是在长网页中延迟加载图片数据,是一种较好的网页性能优化的方式。在比较长的网页或应用中,如果图片很多,所有的图片都被加载出来,而用户只能看到可视窗口的那一部分图片数据,这样就浪费了性能。

  2.当我们在浏览电商网站的时候,需要展示大量的图片(例如图一),但是网站的可视化区域是有限的,如果同时加载所有图片,会导致首屏的加载速度较慢,因为浏览器会把不在可视区域内的图片也一并加载。如果使用图片的懒加载就可以解决以上问题。在滚动屏幕之前,可视化区域之外的图片不会进行加载,在图片进入可视区域后才加载。这样使得网页的加载速度更快,减少了服务器的负载。懒加载适用于图片较多,页面列表较长(长列表)的场景中。

image.png 图一

如何实现懒加载

  1.首先我们需要有个占位图(例如图二):

  占位图也是图片,只不过内存很小,可以很快的加载完,它的主要目的是在内容尚未准备好时,帮助布局和视觉呈现,确保页面结构清晰可见。

image.png

图二

  2.将原有src交给data-original

我们将图片的真实地址暂时存储在数据属性 data-src中,因为浏览器会自动加载src属性指定资源,但是不会加载data-src属性。然后将一个占位图片的地址赋值给src属性,因为占位图通常是一个较小且简单的图像,因此它可以在短时间内快速加载和显示,且浏览器会对已经下载过的资源进行缓存,如果所有图片的占位图使用的是相同的URL,并且浏览器已经缓存了占位图,那么浏览器会进一步加快加载速度。

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>图片懒加载</title>
  <style>
    *{
      margin: 0;
      padding: 0;
    }
    body{
        background-color: black;
    }
    .image-item{
      width: 500px;
      height: 500px;
      margin-bottom: 20px;
    }
  </style>
</head>
<body>
  <img  class="image-item" lazyload="true"  
  src="https://static.360buyimg.com/item/main/1.0.12/css/i/loading.gif" 
  data-original="https://img.36krcdn.com/hsossms/20250313/v2_15ad8ef9eca34830b4a2e081bbc7f57a@000000_oswg172644oswg1536oswg722_img_000?x-oss-process=image/resize,m_mfit,w_960,h_400,limit_0/crop,w_960,h_400,g_center" />
  <img  class="image-item" lazyload="true"  
  src="https://static.360buyimg.com/item/main/1.0.12/css/i/loading.gif" 
  data-original="https://img.36krcdn.com/hsossms/20250312/v2_aeaa7a1d51e74c3a8f909c96cd73a687@000000_oswg169950oswg1440oswg600_img_jpeg?x-oss-process=image/format,webp" />
  <img  class="image-item" lazyload="true"  
  src="https://static.360buyimg.com/item/main/1.0.12/css/i/loading.gif" 
  data-original="https://img.36krcdn.com/hsossms/20250312/v2_1c88dc26ff9341cf8738d670896ce3a8@5284654_oswg847922oswg1440oswg600_img_png?x-oss-process=image/resize,m_mfit,w_960,h_400,limit_0/crop,w_960,h_400,g_center/format,webp" />
  <img class="image-item" lazyload="true"  
  src="https://static.360buyimg.com/item/main/1.0.12/css/i/loading.gif" 
  data-original="https://img.36krcdn.com/hsossms/20250312/v2_e1d92f43af2c4f47b8852ea8786e606f@6100851_oswg635095oswg1053oswg495_img_png?x-oss-process=image/resize,m_mfit,w_960,h_400,limit_0/crop,w_960,h_400,g_center/format,webp" />
  <img  class="image-item" lazyload="true"  
  src="https://static.360buyimg.com/item/main/1.0.12/css/i/loading.gif" 
  data-original="https://img.36krcdn.com/hsossms/20250307/v2_9295b22d4a1b4b55ac4c3379b2da80cc@6100851_oswg781048oswg1053oswg495_img_png?x-oss-process=image/resize,m_mfit,w_600,h_400,limit_0/crop,w_600,h_400,g_center/format,webp" />
  <img  class="image-item" lazyload="true"  
  src="https://static.360buyimg.com/item/main/1.0.12/css/i/loading.gif" 
  data-original="https://img.36krcdn.com/hsossms/20250306/v2_6ea048ac01c3408a9ed6ebe79a8fc8a2@5888275_oswg849213oswg1053oswg495_img_png?x-oss-process=image/resize,m_mfit,w_600,h_400,limit_0/crop,w_600,h_400,g_center/format,webp" />
  <img  class="image-item" lazyload="true"  src="https://static.360buyimg.com/item/main/1.0.12/css/i/loading.gif" data-original="https://img.36krcdn.com/hsossms/20250312/v2_e4c73b024bcc409fba427adb2d7fb2fa@000000_oswg1251602oswg1080oswg559_img_000?x-oss-process=image/format,jpg/interlace,1" />
  <img class="image-item" lazyload="true"  src="https://static.360buyimg.com/item/main/1.0.12/css/i/loading.gif" data-original="https://img.36krcdn.com/hsossms/20250312/v2_9f21750bb37243128b6b1790f9072649@000000_oswg1219724oswg1080oswg601_img_000?x-oss-process=image/format,jpg/interlace,1" />
  <img  class="image-item" lazyload="true"  src="https://static.360buyimg.com/item/main/1.0.12/css/i/loading.gif" data-original="https://img.36krcdn.com/hsossms/20250312/v2_2acf9b228cd940c1b5fdb5691c0b6e4c@000000_oswg1402679oswg1080oswg527_img_000?x-oss-process=image/format,jpg/interlace,1" />
  <img  class="image-item" lazyload="true"  src="https://static.360buyimg.com/item/main/1.0.12/css/i/loading.gif" data-original="https://img.36krcdn.com/hsossms/20250312/v2_af4dd443d261445d8e903c473cac074c@000000_oswg1118331oswg1080oswg497_img_000?x-oss-process=image/format,jpg/interlace,1" />
  <img  class="image-item" lazyload="true" src="https://static.360buyimg.com/item/main/1.0.12/css/i/loading.gif" data-original="https://img.36krcdn.com/hsossms/20250313/v2_e7de1cc8e8014122ba303ea036eea532@1743780481_oswg58583oswg1080oswg257_img_000?x-oss-process=image/format,jpg/interlace,1" />
  <img  class="image-item" lazyload="true" src="https://static.360buyimg.com/item/main/1.0.12/css/i/loading.gif" data-original="https://img.36krcdn.com/hsossms/20250313/v2_0f70e0a75a8d4736a050e846cd6ab3e5@1743780481_oswg183216oswg1080oswg629_img_000?x-oss-process=image/format,jpg/interlace,1" />
  
</body>
</html>

这是一段只加了占位图的代码,运行结果为图三

image.png

图三

  3.监听事件处理以及可视区域显示

 const viewHeight = document.documentElement.clientHeight;
    // console.log(viewHeight);
    const eles =document.querySelectorAll('img[data-original][lazyload]');
    const lazyload =function(){
        // 类数组  
        Array.prototype.forEach.call(eles,function(item,index){
        console.log(item);
        // 没有值,退出 data-original item.dataset.original 
        if(item.dataset.original === ""){
            return ;
        }
        // img 标签对象在视口的位置 
        rect=item.getBoundingClientRect();
        // console.log(rect);
        if(rect.bottom >=0 && rect.top < viewHeight){
            // 有必要渲染
            (function(){
              var img =new Image(); // 内存中的img 对象 
            //   document.body.appendChild(img);
            img.src=item.dataset.original;
            img.onload = function(){
                // 加载完成
                // cahce 
                // 异步
                item.src =item.dataset.original;// item 是dom对象  图片太大,网速慢 
                item.removeAttribute('data-original');// 性能,不用在迭代item
                item.removeAttribute('lazyload');// 性能,不用在迭代item
            }
            })()
        }
      })
    }
    // console.log(eles);
    window.addEventListener('scroll',lazyload);
    document.addEventListener('DOMContentLoaded',lazyload);

document.documentElement.clientHeight; 可以获取当前视口高度 document.querySelectorAll('img[data-original][lazyload]'); 获取所有带 data-original 和 lazyload 属性的 img 标签

总结

图片懒加载是前端性能优化的重要策略之一,通过延迟加载不在视窗范围内的图片,可以显著减少页面初次加载时的HTTP请求数,加快页面加载速度。同时结合节流、缓存等技术手段,可以进一步提升懒加载的性能和用户体验。如果想要成为一个优秀的前端工程师,在开发过程中我们就应该应充分重视像图片懒加载这样的前端性能优化工作,为用户提供更快速、更流畅的网页浏览体验。