JavaScript实现图片懒加载与预加载的代码详解

作者:代码拾荒时间:2026-11-01 04:25:58浏览:548

本文详细解析前端开发中图片懒加载与预加载的实现原理及代码。通过监听滚动事件与getBoundingClientRect判断可视区域实现懒加载,利用Web Worker异步加载资源实现预加载,旨在解决大量图片导致的网络堵塞与服务器压力问题,提升页面加载速度与用户体验。

引言

图片懒加载与预加载是前端性能优化中常用的策略,也是前端面试中频繁涉及的技术点。懒加载机制指页面初始加载时,仅渲染可视区域内的内容,非可视区域的图片暂不请求,待用户滚动至该位置时才发起加载;预加载则相反,在页面初始化阶段一次性将所有图片资源加载完毕。

若不对图片加载进行优化,浏览器会因大量图片请求导致频繁的回流与重绘,进而引发网络拥堵。当页面包含数百甚至上千张图片时,并发的大量网络请求会严重拖慢加载速度,损害用户体验。下文将具体演示如何实现这两种加载效果。

懒加载

懒加载的核心原理是监听页面的滚动事件,实时检测图片元素是否进入可视窗口,仅在图片即将可见时触发加载。可通过JavaScript中的getBoundingClientRect()方法获取元素的几何位置信息,具体输出结构如下。

<body>
  <img src="" data-src="https://t7.baidu.com/it/u=1732966997,2981886582&fm=193&f=GIF" alt="">
  <script>
    let img = document.querySelector('img')
    let rect = img.getBoundingClientRect()  // 获取元素几何属性
    console.log(rect);
  </script>
</body>

引言

该对象包含left(元素左边框距视口左边的距离)、right(元素右边框距视口左边的距离)、bottom(元素下边框距视口上边的距离)以及top(元素上边框距视口上边的距离)等属性。

判断图片是否位于可视区域内的逻辑为:图片的top值小于窗口高度,且bottom值大于0。

为避免图片在加载前显示占位符或错误图标,不应直接将图片URL置于src属性中。可在img标签中自定义data-src属性存储真实图片地址,当图片进入可视区域时,将该属性值赋给src以触发加载;加载完成后,移除data-src属性以清理DOM。

<img src="" data-src="https://t7.baidu.com/it/u=17329669972981886582&fm=193&f=GIF" alt="">
<script>
    let height = window.innerHeight

    function lazyLoad() {
      const imgs = document.querySelectorAll('[data-src]')
      // console.log(imgs);
      for (let i = 0; i < imgs.length; i++) {
        let rect = imgs[i].getBoundingClientRect() // 获取元素的集合属性
        if (rect.bottom > 0 && rect.top < height) {
          imgs[i].src = imgs[i].getAttribute('data-src')

          imgs[i].onload = function () {   // 图片被浏览器加载完毕
            imgs[i].src = imgs[i].getAttribute('src')
          }

          imgs[i].removeAttribute('data-src')
        }
      }
    }

    lazyLoad()

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

此外,代码中的imgs[i].src = imgs[i].getAttribute('data-src')部分可替换为以下实现:

// imgs[i].src = imgs[i].getAttribute('data-src')
// imgs[i].onload = function () {     // 图片被浏览器加载完毕
//     imgs[i].src = imgs[i].getAttribute('src')
//  }
 
// 换成

let newImg = new Image()    
newImg.src = imgs[i].getAttribute('data-src')   // 读取 url
newImg.onload = function () { // 图片被浏览器加载完毕
    imgs[i].src = newImg.getAttribute('src')     
}

此举旨在将图片加载过程异步化,从而降低对主线程的阻塞压力。具体做法是创建一个新的Image实例,通过设置其src属性来预加载图片。当图片加载完成(触发onload事件)后,将图片的src属性赋值给原有的img元素,完成渲染。

最终运行效果如下:

引言

预加载

预加载机制在用户打开页面时即开始加载所有图片,使得后续滚动操作极为流畅。然而,这种策略会导致短时间内产生大量网络请求,给服务器带来较大负载压力。

其原理是在页面加载的同时,利用独立线程加载图片资源,待资源就绪后交由主线程进行渲染展示,以此实现预加载效果。

具体实现代码如下:

  <div id="pic"></div>

  <script>
    let pic = document.getElementById('pic')

    let arr = [xxxxx]   // 图片资源
    // 创建一个新的线程
    const worker = new Worker('worker.js')
    // 将数据发送给子线程
    worker.postMessage(arr)
  </script>

是浏览器内置方法,用于将Blob对象转换为可访问的URL地址。

函数是JavaScript原生的构造函数,用于创建一个新的Web Worker线程。需要注意的是,该新线程无法直接操作DOM结构。主线程与Worker线程之间通过postMessage API进行通信。

// worker.js   self就是worker

self.onmessage = function (e) {
  // console.log(e.data);   // 传过来的图片资源
  // 将数组中的地址资源加载出来
  let arr = e.data;
  for (let i = 0; i < arr.length; i++) {
    let xhr = new XMLHttpRequest();
    xhr.open("get", arr[i], true);
    xhr.responseType = 'blob'  // 文件类型
    xhr.send();
    xhr.onload = function () {
      if (xhr.readyState === 4 && xhr.status === 200) {
        // console.log(xhr.response);
        self.postMessage(xhr.response);   //将图片发送给主线程
      }
    }
  }
}

在worker.js文件中,通过HTTP请求加载图片资源,获取的数据类型为Blob文件。

<body>
  <div id="pic"></div>

  <script>
    let pic = document.getElementById('pic')

    let arr = [xxxxx]   // 图片资源
    // 创建一个新的线程
    const worker = new Worker('worker.js')
    // 将数据发送给子线程
    worker.postMessage(arr)
    // 接收子线程发送的数据
    worker.onmessage = function (e) {
      console.log(e.data);
      const img = new Image()
      // console.log(window.URL.createObjectURL(e.data));
      img.src = window.URL.createObjectURL(e.data)
      pic.appendChild(img)
    }
  </script>
</body>

window.URL.createObjectURL(e.data)是window自带的方法,作用就是将blob资源转换成url。

小结

  • 懒加载原理:页面加载完成后,优先渲染可视区域内的图片;当用户滚动页面时,实时检测图片是否进入可视区域,若进入,则将图片的src属性替换为真实路径,从而实现按需加载。
  • 预加载原理:在页面加载阶段,开启独立线程异步加载图片资源;待资源加载完毕后,将数据传递回主线程进行展示,从而实现预加载。

以上就是JavaScript实现图片懒加载与预加载的代码详解的详细内容,更多关于JavaScript图片懒加载与预加载的资料请关注本站其它相关文章!

作者最新文章