图片懒加载
图片懒加载是一种优化网页性能的技术,主要作用是延迟加载视口外的图片,直到用户滚动到它们附近时才加载
以下是常见的几种实现方式
1. 传统滚动事件监听方式
- 监听到
scroll事件后,调用目标元素的getBoundingClientRect()方法来实现。
function lazyLoad() {
const images = document.querySelectorAll('img[data-src]');
images.forEach(img => {
if (img.getBoundingClientRect().top < window.innerHeight + 100) {
img.src = img.dataset.src;
}
});
}
window.addEventListener('scroll', lazyLoad);
window.addEventListener('resize', lazyLoad);
lazyLoad(); // 初始加载
缺点:性能较差,需要手动处理节流
2、使用Intersection Observer API(现代推荐方式)
通过IntersectionObserverAPI 来实现,他可以自动"观察"元素是否可见。由于可见(visible)的本质是,目标元素与视口产生一个交叉区,所以这个 API 叫做"交叉口观测器"。
const images = document.querySelectorAll('img[data-src]');
const observer = new IntersectionObserver((entries) => {
// entries 是一个数组,包含了我们所需要监听的所有图片对象的信息
entries.forEach(entry => {
if (entry.isIntersecting) {
const img = entry.target;
img.src = img.dataset.src;
observer.unobserve(img); // 停止监听
}
});
});
// 添加需要监听的图片
images.forEach(img => observer.observe(img));
优点:性能好,不阻塞主线程,代码简洁
IntersectionObserver是浏览器原生提供的构造函数,可以自动‘观察’元素是否可见。
//观察器实例
const io = new IntersectionObserver(callback,options)
参数
-
callback:是可见性变化时的回调函数。callback一般会触发两次- 一次是目标元素刚刚进入视口(开始可见)
- 另一次是完全离开视口(开始不可见)
-
option:是配置对象(该参数可选) 优点:性能好,不阻塞主线程,代码简洁
返回值:一个观察期实例
观察器实例方法:
-
observe方法可以指定观察哪个DOM节点,就需要多次调用observe方法 -
unobserve方法用于停止对某个元素的观察 -
disconnect方法用于关闭观察器
//开始观察box元素和container
io.server(document.getElementById('box'))
io.server(document.getElementById('container'))
//停止观察box元素
io.unobserve(document.getElementById('box'))
//关闭观察器
io.disconnect();
3. 使用loading="lazy"属性(HTML原生支持)
<img src="image.jpg" loading="lazy" alt="...">
优点:最简单的方式,现代浏览器都支持
缺点:兼容性问题(IE不支持),控制粒度较粗
4、第三方库实现
常用库:
- lazysizes
- lozad.js
- vanilla-lazyload
以下是插件vanilla-lazyload的具体使用
进入 https://www.npmjs.com/ 官网,然后在搜索框中输入 vanilla-lazyload 回车 ,即可找到该插件
5. 框架内置懒加载
-
React: 使用
react-lazyload等库 -
Vue: 有
vue-lazyload插件 - Angular: 有内置的懒加载支持
实现要点
- 使用
data-src自定义属性代替src属性存储真实图片URL - 设置占位图(可以是小尺寸预览图或纯色背景)
- 考虑添加加载动画或过渡效果
- 对于重要图片(如首屏)不要使用懒加载
选择哪种方式取决于项目需求、目标浏览器支持和开发环境。现代项目推荐优先使用Intersection Observer或原生loading属性。