一文搞懂JavaScript如何实现图片懒加载
本文深入解析JavaScript实现图片懒加载的核心原理,通过监听滚动事件、利用data-*属性存储真实地址,并结合节流函数优化性能。文章详细讲解了getBoundingClientRect()的使用及各类Height属性的区别,提供完整JS与CSS代码示例,帮助开发者有效减少首屏加载时间,提升网页渲染效率。
图片懒加载通常被用作减少首页白屏时间的一种解决方案。其核心逻辑在于不立即加载所有图片,而是根据特定条件在合适时机进行加载,即所谓的“惰性加载”。虽然可以直接使用如vue-lazyload等第三方插件来简化开发,但理解其底层实现原理有助于更好地掌控性能。本文将详细拆解如何从零开始实现这一功能。
实现思路
要实现图片懒加载,首先需明确应用场景。通常策略是首屏直接加载少量图片,其余图片暂不加载,仅在页面滚动至图片即将进入可视区域时才触发加载。这样做的原因在于,当页面包含大量图片时,一次性加载所有图片会导致严重的白屏现象,尤其是图片体积较大时,页面渲染延迟会显著增加用户体验问题。
实现过程:
- 使用
data-*自定义数据属性给img标签新增一个data-src属性 - 全局监听滚动事件,使用节流处理回调函数
- 在回调函数中,判断图片是否已经出现在可视区域,如果已经出现在可视区域,则加载该图片
- 页面初始化的时候执行一下回调函数,保证首屏有图片显示
在这个实现过程中,涉及一些知识点,我们来快速回顾一下:
准备知识
data-*
data-*是可自定义数据属性的属性,可用在所有的HTML元素上面,嵌入自定义的数据内容。这些自定义的数据可以在HTMMLElement.dataset中被访问到,例如:
<img id="img" src="loading.gif" data-src="xxx.png" data-name="img" />
// 访问dataset
const img = document.getElementById('img')
console.log(img.dataset.src); // xxx.png
console.log(img.dataset.name); // img
我们实现图片懒加载的最终目的,就是在恰当的时候使用data-src的值替换到src,加载真实的图片。data-*定义的数据不仅可以在js中访问,也可以在CSS中访问,具体可参考:dataset
getBoundingClientRect()
Element.getBoundingClientRect()方法会返回一个DOMRect对象,其包含了当前元素的大小,以及相对于视窗的位置信息。听名字可能会有点迷糊,但是结合图来看就比较好理解了:

DOMRect对象中的width和height是包含了元素的padding和border-width,其位置信息指的是包含元素的最小矩形的每条边距离视窗原点(0,0)的位置。
throttle
由于我们会全局监听scroll滚动事件,如果每次滚动都触发回调函数的话会造成不必要的计算成本,因此我们考虑使用节流来处理滚动事件。节流的具体细节就不在此重复,我们先简单实现一个节流:
function throttle(fn, delay = 200) {
let timer = null;
return function() {
if (timer) return;
timer = setTimeout(() => {
fn.apply(this, arguments);
timer = null;
}, delay);
}
}
window.innerHeight
有几个很相似的”height“,我们就简单都梳理一下:
window.innerHeight:浏览器可视区域的高度;如果有水平滚动条,也会包含滚动条高度window.outerHeight:获取整个浏览器的高度Element.scrollHeight:元素内容的高度,包括由于溢出导致隐藏的内容高度Element.clientHeight:元素内部的高度,包含内边距,但不包括水平滚动条、边框、外边距
这里我们使用innerHeight即可,因为我们是在window对象上监听scroll滚动事件。
准备工作已经完毕,接下来就直接上手代码。
完整代码
代码中都有相应的注释,在了解上面的准备知识后,代码就挺简单的了:
js部分
// 使用for循环批量创建img,html中可没有v-for可以使用
for (let index = 0; index < 10; index++) {
let img = document.createElement("img");
img.src = "./loading.gif";
img.dataset.src = "./dog.jfif"; // 由于我们是通过js创建的,因此就无法直接使用data-*,如果是在html上面,需要添加此属性
document.body.appendChild(img);
img = null;
}
// 节流
function throttle(fn, delay = 200) {
let timer = null;
return function () {
if (timer) return;
timer = setTimeout(() => {
fn.apply(this, arguments);
timer = null;
}, delay);
};
}
// 懒加载-回调函数
function lazyLoad() {
const imgs = document.querySelectorAll('img[data-src]');
if (!imgs.length) return;
imgs.forEach(img => {
const rect = img.getBoundingClientRect();
if (rect.top < window.innerHeight) {
img.src = img.dataset.src;
img.removeAttribute('data-src'); // 我们是通过img[data-src]查找所有img标签的,渲染后就删除data-src可减少forEach循环的计算成本
}
})
}
// 全局监听scroll滚动事件
window.addEventListener('scroll', throttle(() => {
lazyLoad();
}, 100));
// 初始化的时候执行一下加载图片的函数
lazyLoad();
CSS部分
<style>
body {
display: flex;
flex-direction: column;
align-items: center;
}
img {
margin: 10px auto;
width: 600px;
height: 400px;
object-fit: cover;
border-radius: 4px;
border: 1px solid #070707;
}
</style>
运行结果
首屏展示:

首先我们会默认加载三张图片,查看元素节点,这三张图片的data-src都没有,而另外没有加载的图片是有data-src的。
滚动中展示:

滚动时会触发图片加载的回调函数,DOM树也会跟着改变
滚动结束展示

所有图片都将只有src,没有data-src。
总结
本文通过监听滚动事件,在图片出现在可视区域前才加载真正的图片,如果未出现则使用默认的loading图片的方式实现了图片懒加载。一般来说,loading图片都会比较小,而实际的图片会大很,因此使用loading图片来代替是可以减少图片渲染时间的。
到此这篇关于一文搞懂JavaScript如何实现图片懒加载的文章就介绍到这了,更多相关JavaScript图片懒加载内容请搜索本站以前的文章或继续浏览下面的相关文章希望大家以后多多支持本站!
JS处理特殊字符时怎么安全生成JSON
2026-11-05 15:44:51
内部脚本与外部js文件的区别及优缺点对比
2026-11-05 14:42:19
JavaScript前端性能优化指南:提升页面加载速度与渲染效率
2026-11-05 13:48:26
主流JS反混淆工具对比:de4js、unminify与AST还原方案评测
2026-11-05 12:00:56
Nuxt.js 性能优化技巧:代码分割与组件懒加载
2026-11-03 23:32:56








