图片当了一天牛马,让它偷懒一下不过分吧——图片懒加载

135 阅读4分钟

什么是图片懒加载?

图片懒加载(Lazy Loading)是一种前端性能优化技术,它能让图片在 进入视口时才开始加载 ,而非页面初始时全部加载。这就像餐厅的"按需上菜",避免了一开始就把所有菜品(图片资源)都端上桌(浏览器请求)造成的资源浪费。

在电商网站、图片画廊等场景中,一个页面可能包含几十甚至上百张图片。如果不做优化,浏览器会在页面加载时同时请求所有图片资源,导致:

  • 首屏加载缓慢,用户需要等待更长时间
  • 浪费带宽,尤其对移动用户不友好
  • 增加服务器负载,并发请求过多 中明确指出:"img太多会严重影响页面的打开速度",而懒加载正是解决这个问题的关键方案。

懒加载的实现原理

核心思路

牛马图片的内心独白 : "上班(页面加载)先摸鱼(不加载),老板(用户)走到面前(进入视口)再假装工作(开始加载)"

  1. 初始摸鱼状态 :图片的真实地址不放在 src 属性中,而是藏在自定义属性(如 data-original)里摸鱼
  2. 占位表演 :src 属性使用极小的占位图或透明像素假装在工作
  3. 老板巡视监听 :检测图片元素是否进入视口(老板是否过来巡视)
  4. 被迫营业 :当图片进入视口时,才把 data-original 的值赋给 src 属性开始加载
<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" />

关键技术点

  • 视口检测 :判断元素是否可见(老板有没有看到)
  • 资源加载 :动态设置图片地址(被迫开始工作)
  • 摸鱼优化 :避免频繁触发检测逻辑(别老盯着我看)

两种实现方案对比

方案一:传统滚动监听 + 位置计算

这是最经典的实现方式,通过监听 scroll 事件,结合 getBoundingClientRect() 方法判断元素位置。就像牛马人每隔5分钟抬头看看老板来了没有,效率低但兼容性好。

<script>
    const viewHeight = document.documentElement.clientHeight; // 视口高度(老板视线范围)
    const eles = document.querySelectorAll('img[data-original][lazyload]'); // 所有摸鱼图片

    const lazyload = function() {
        // 遍历所有需要懒加载的图片(检查每个牛马的工作状态)
        Array.prototype.forEach.call(eles, function(item) {
            // 如果没有原始地址,则跳过(已经被抓包的不用管)
            if(item.dataset.original === "") return;
            
            // 获取元素位置信息(牛马离老板的距离)
            const rect = item.getBoundingClientRect();
            
            // 当元素进入视口(老板看到了)
            if(rect.bottom >= 0 && rect.top < viewHeight) {
                // 创建新图片对象(准备工作)
                const img = new Image();
                img.src = item.dataset.original; // 开始加载真实图片
                
                img.onload = function() {
                    // 加载完成后替换占位图(开始工作)
                    item.src = item.dataset.original;
                    // 移除标记属性(已经被抓包,不用再检查)
                    item.removeAttribute('data-original');
                    item.removeAttribute('lazyload');
                };
            }
        });
    };

    // 监听滚动事件(老板随时可能巡视)
    window.addEventListener('scroll', lazyload);
    // 初始页面加载时检查一次
    document.addEventListener('DOMContentLoaded', lazyload);
</script>

牛马评价: "这种方式就像手动打卡,每隔几秒就要抬头看老板,累得要死还容易漏看(频繁触发 scroll 事件导致性能问题)"

方案二:IntersectionObserver 智能监听

HTML5 新增的 IntersectionObserver API 可以自动监听元素是否进入视口,就像给每个牛马配了个智能打卡机,老板来了自动提醒,效率大大提升!

现代实现代码(可替换原有 scroll 监听方案):

<script>
    // 创建观察者实例(智能打卡机)
    const observer = new IntersectionObserver((entries, observer) => {
        entries.forEach(entry => {
            if (entry.isIntersecting) { // 当元素进入视口(老板进入视线)
                const img = entry.target;
                const src = img.dataset.original;
                
                if (src) {
                    img.src = src; // 加载图片(开始工作)
                    
                    img.onload = function() {
                        img.classList.add('loaded');
                        img.removeAttribute('data-original');
                        img.removeAttribute('lazyload');
                    };
                    
                    observer.unobserve(img); // 停止观察(打完卡就下班)
                }
            }
        });
    }, {
        rootMargin: '0px 0px 200px 0px', // 提前200px开始加载(提前准备好工作)
        threshold: 0.1
    });

    // 获取所有需要懒加载的图片并观察(给每个牛马配打卡机)
    document.querySelectorAll('img[data-original][lazyload]').forEach(img => {
        observer.observe(img);
    });
</script>

牛马评价: "这个好!配了智能打卡机(IntersectionObserver),我可以安心摸鱼,老板快来了会自动提醒,再也不用频繁抬头看了!"

懒加载总结

Snipaste_2025-07-13_18-32-54.png

牛马人终极建议 :现代项目直接用 IntersectionObserver,配个 polyfill 兼容旧浏览器,摸鱼效率最大化!

结语

图片懒加载就像牛马人的摸鱼哲学: 不该干的活不主动干,该干的活不拖延 。合理使用懒加载技术,既能提升页面性能,又能减少资源浪费,何乐而不为呢?

最后用一句话共勉:"前端优化就像挤牙膏,多一点耐心,就能挤出更多性能(摸鱼时间)"。