Interview AiBoxInterview AiBox 实时 AI 助手,让你自信应答每一场面试
请解释图片懒加载的原理和实现方式
题型摘要
图片懒加载是一种延迟加载非可视区域图片的性能优化技术。主要实现方式有四种:基于滚动事件监听(兼容性好但性能差)、基于Intersection Observer API(现代高效方式)、使用loading属性(原生支持,最简单)以及第三方库(功能丰富)。最佳实践是优先使用原生懒加载,必要时结合Intersection Observer API,并添加占位图和提前加载以提升用户体验。
图片懒加载的原理和实现方式
定义与原理
图片懒加载(Lazy Loading)是一种网页性能优化技术,它延迟加载页面中非可视区域的图片,只有当图片即将进入用户可视区域时才进行加载。这样可以减少初始页面加载时间、降低服务器负载和节省带宽。
为什么需要图片懒加载
- 提升页面加载速度:只加载可视区域内的图片,减少初始HTTP请求数量
- 节省带宽资源:用户可能不会滚动到页面底部,不必要加载所有图片
- 提升用户体验:页面可以更快地呈现主要内容,减少用户等待时间
- 减轻服务器压力:减少不必要的图片请求,降低服务器负载
实现方式
1. 基于滚动事件监听
原理:
- 给图片设置一个自定义属性(如
data-src)存储真实图片地址,src属性可以设置为空或占位图 - 监听滚动事件,计算每个图片元素的位置与可视区域的关系
- 当图片进入可视区域时,将
data-src的值赋给src属性,触发图片加载
代码示例:
document.addEventListener("DOMContentLoaded", function() {
let lazyImages = [].slice.call(document.querySelectorAll("img.lazy"));
if ("IntersectionObserver" in window) {
// 如果浏览器支持Intersection Observer,使用更高效的方式
} else {
// 回退到滚动事件监听方式
let active = false;
const lazyLoad = function() {
if (active === false) {
active = true;
setTimeout(function() {
lazyImages.forEach(function(lazyImage) {
if ((lazyImage.getBoundingClientRect().top <= window.innerHeight && lazyImage.getBoundingClientRect().bottom >= 0) && getComputedStyle(lazyImage).display !== "none") {
lazyImage.src = lazyImage.dataset.src;
lazyImage.classList.remove("lazy");
lazyImages = lazyImages.filter(function(image) {
return image !== lazyImage;
});
if (lazyImages.length === 0) {
document.removeEventListener("scroll", lazyLoad);
window.removeEventListener("resize", lazyLoad);
window.removeEventListener("orientationchange", lazyLoad);
}
}
});
active = false;
}, 200);
}
};
document.addEventListener("scroll", lazyLoad);
window.addEventListener("resize", lazyLoad);
window.addEventListener("orientationchange", lazyLoad);
lazyLoad();
}
});
优点:
- 兼容性好,支持所有主流浏览器
- 实现简单直观
缺点:
- 滚动事件频繁触发,性能较差
- 需要手动计算元素位置,代码复杂
- 滚动事件处理函数需要做节流处理,否则会影响性能
2. 基于Intersection Observer API
Intersection Observer API是现代浏览器提供的一种异步检测目标元素与祖先元素或视口相交情况的方法。它是实现懒加载的更高效方式。
原理:
- 创建一个Intersection Observer实例,配置回调函数和选项
- 观察所有需要懒加载的图片元素
- 当图片元素进入可视区域时,触发回调函数,加载图片
代码示例:
document.addEventListener("DOMContentLoaded", function() {
var lazyImages = [].slice.call(document.querySelectorAll("img.lazy"));
if ("IntersectionObserver" in window) {
let lazyImageObserver = new IntersectionObserver(function(entries, observer) {
entries.forEach(function(entry) {
if (entry.isIntersecting) {
let lazyImage = entry.target;
lazyImage.src = lazyImage.dataset.src;
lazyImage.classList.remove("lazy");
lazyImageObserver.unobserve(lazyImage);
}
});
}, {
rootMargin: "0px 0px 200px 0px" // 提前200px加载
});
lazyImages.forEach(function(lazyImage) {
lazyImageObserver.observe(lazyImage);
});
} else {
// 回退到滚动事件监听方式
}
});
优点:
- 性能更好,由浏览器内部优化,不依赖主线程
- 代码更简洁,不需要手动计算元素位置
- 可以配置提前加载的距离(rootMargin)
- 不需要节流处理
缺点:
- 不支持旧版浏览器(如IE)
- 需要添加polyfill以支持更多浏览器
3. 使用loading属性(原生懒加载)
现代浏览器(Chrome 76+、Firefox 75+、Edge 79+)支持原生的图片懒加载,只需给<img>标签添加loading="lazy"属性。
原理:
- 浏览器原生支持,无需JavaScript
- 浏览器自动判断图片是否进入可视区域,并决定何时加载
代码示例:
<img src="image.jpg" loading="lazy" alt="..." width="200" height="200">
优点:
- 实现最简单,只需添加一个属性
- 性能最好,由浏览器内部优化
- 无需额外JavaScript代码
缺点:
- 浏览器支持有限,不兼容所有浏览器
- 可定制性差,无法控制加载时机和提前加载的距离
4. 使用第三方库
有许多成熟的第三方库可以实现图片懒加载,如:
- lozad.js
- lazysizes
- yall.js
- Echo.js
原理:
- 这些库封装了懒加载的逻辑,通常基于Intersection Observer API或滚动事件
- 提供更多功能和配置选项
代码示例(以lozad.js为例):
<!-- 引入lozad.js -->
<script src="https://cdn.jsdelivr.net/npm/lozad/dist/lozad.min.js"></script>
<!-- HTML -->
<img class="lozad" data-src="image.jpg" alt="...">
<!-- JavaScript -->
<script>
const observer = lozad(); // 默认配置
observer.observe();
</script>
优点:
- 功能丰富,通常提供更多配置选项
- 已经处理了各种边界情况和兼容性问题
- 可能包含额外功能,如占位图、加载动画等
缺点:
- 增加项目依赖和体积
- 可能包含不需要的功能
实现方式对比
| 实现方式 | 兼容性 | 性能 | 实现难度 | 可定制性 |
|---|---|---|---|---|
| 滚动事件监听 | 高 | 差 | 中 | 高 |
| Intersection Observer API | 中 | 高 | 低 | 高 |
| loading属性 | 低 | 最高 | 最低 | 低 |
| 第三方库 | 高 | 中高 | 最低 | 中高 |
最佳实践
- 优先使用原生懒加载:如果不需要支持旧浏览器,优先使用
loading="lazy"属性 - 使用Intersection Observer API:需要兼容更多浏览器时,使用Intersection Observer API,并提供滚动事件监听作为回退方案
- 考虑使用第三方库:如果项目需要更多功能或不想处理实现细节,可以使用成熟的第三方库
- 添加占位图:为未加载的图片添加占位图或背景色,避免页面布局跳动
- 提前加载:设置适当的提前加载距离,提升用户体验
- 考虑图片格式:使用现代图片格式如WebP,减少图片体积
- 响应式图片:结合
srcset和sizes属性,为不同设备提供适当大小的图片
思维导图
Interview AiBoxInterview AiBox — 面试搭档
不只是准备,更是实时陪练
Interview AiBox 在面试过程中提供实时屏幕提示、AI 模拟面试和智能复盘,让你每一次回答都更有信心。
AI 助读
一键发送到常用 AI
图片懒加载是一种延迟加载非可视区域图片的性能优化技术。主要实现方式有四种:基于滚动事件监听(兼容性好但性能差)、基于Intersection Observer API(现代高效方式)、使用loading属性(原生支持,最简单)以及第三方库(功能丰富)。最佳实践是优先使用原生懒加载,必要时结合Intersection Observer API,并添加占位图和提前加载以提升用户体验。
智能总结
深度解读
考点定位
思路启发
相关题目
请做一个自我介绍
自我介绍是面试的开场环节,应遵循"三段式"结构:基本信息与教育背景、核心能力与项目经验、求职动机与个人特质。重点突出与岗位相关的技能和经验,用具体数据和成果支撑,保持真诚自然的表达,控制在2-3分钟内。针对不同公司和岗位进行个性化调整,展示自己的匹配度和价值。
你有什么问题想问我们公司或团队的吗?
面试结尾提问是展示面试者思考深度和职业素养的重要机会。应提前准备3-5个有深度的问题,围绕团队技术、个人成长、公司文化和业务发展四个方面。好的问题能体现你对公司的了解、对职位的重视以及你的职业规划,避免问基础信息类问题。
请做一个自我介绍
自我介绍应遵循“我是谁-我为什么能胜任-我为什么想来”的逻辑框架。在“能胜任”部分,要通过STAR法则和量化结果来突出技术亮点和项目经验。在“想来”部分,要表达对华为技术、文化或业务的认同,展现匹配度和诚意。整个过程应简洁有力,控制在1-3分钟内。
请做一个自我介绍
自我介绍是面试的开场环节,应简洁明了地展示个人基本信息、教育背景、项目经验、技术特长、个人特质和求职动机。优秀的自我介绍应结构清晰、重点突出,与应聘岗位高度匹配,并表达出对公司的了解和加入的强烈意愿。
请做一个自我介绍,包括你的技术背景、项目经验和学习方向。
自我介绍应包含四个核心部分:个人背景、技术能力、项目经验和学习规划。技术背景需突出前端技术栈掌握程度;项目经验应选择代表性案例,说明技术实现和个人贡献;学习方向要体现职业规划与公司发展的契合度。整体表达应简洁有力,重点突出,时间控制在3-5分钟内。