本文详细解析前端开发中图片懒加载与预加载的实现原理及代码。通过监听滚动事件与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图片懒加载与预加载的资料请关注本站其它相关文章!