图片异步加载是优化网页性能的重要技术,可以减少初始页面加载时间,提升用户体验。以下是几种实现图片异步加载的方法:
loading="lazy"
属性(原生懒加载)
<img src="image.jpg" loading="lazy" alt="示例图片">
这是HTML5原生支持的懒加载方式,现代浏览器都支持。当图片接近视口时才会加载。
<img class="lazy" data-src="image.jpg" alt="示例图片">
<script>
document.addEventListener("DOMContentLoaded", function() {
const lazyImages = document.querySelectorAll("img.lazy");
if ("IntersectionObserver" in window) {
const imageObserver = new IntersectionObserver((entries, observer) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
const img = entry.target;
img.src = img.dataset.src;
img.classList.remove("lazy");
imageObserver.unobserve(img);
}
});
});
lazyImages.forEach(img => imageObserver.observe(img));
} else {
// 回退方案
lazyImages.forEach(img => {
img.src = img.dataset.src;
});
}
});
</script>
<img src="low-quality-placeholder.jpg"
data-src="high-quality-image.jpg"
class="lazy"
alt="示例图片">
<picture>
<source data-srcset="large.jpg" media="(min-width: 1200px)">
<source data-srcset="medium.jpg" media="(min-width: 768px)">
<img src="placeholder.jpg" data-src="small.jpg" class="lazy" alt="响应式图片">
</picture>
常用的图片懒加载库:
为懒加载图片设置合适的宽高,避免布局偏移
使用占位符保持布局稳定
对关键图片(如首屏图片)不要使用懒加载
考虑使用模糊或低质量图片作为初始占位
为不支持JavaScript的环境提供回退方案
懒加载可能会影响SEO,确保搜索引擎爬虫能访问到重要图片
过度使用懒加载可能会延迟内容显示,需要平衡
移动设备上可能需要调整触发加载的阈值
如果文章内的插图没有原生的loading="lazy"
标签,可以通过以下几种方法实现异步加载:
// 在DOM加载完成后执行
document.addEventListener('DOMContentLoaded', function() {
// 获取所有文章内的img标签(假设文章在<article>内)
const articleImages = document.querySelectorAll('article img');
// 为每个图片添加loading="lazy"属性
articleImages.forEach(img => {
img.loading = 'lazy';
});
});
document.addEventListener('DOMContentLoaded', function() {
const images = document.querySelectorAll('article img:not([loading])');
if ('IntersectionObserver' in window) {
const imgObserver = new IntersectionObserver((entries, observer) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
const img = entry.target;
// 如果图片使用了data-src属性
if (img.dataset.src) {
img.src = img.dataset.src;
}
imgObserver.unobserve(img);
}
});
}, {
rootMargin: '200px 0px' // 提前200px加载
});
images.forEach(img => {
// 如果图片没有src属性但有data-src,先不加载
if (!img.src && img.dataset.src) {
imgObserver.observe(img);
}
// 如果有src但想延迟加载,可以这样处理
else if (img.src) {
const originalSrc = img.src;
img.removeAttribute('src');
img.dataset.src = originalSrc;
imgObserver.observe(img);
}
});
} else {
// 不支持IntersectionObserver的备用方案
images.forEach(img => {
if (img.dataset.src) {
img.src = img.dataset.src;
}
});
}
});
function lazyLoadImages() {
const images = document.querySelectorAll('article img:not([loading])');
const windowHeight = window.innerHeight;
images.forEach(img => {
const imgPosition = img.getBoundingClientRect().top;
if (imgPosition - windowHeight <= 0) {
// 如果使用data-src属性
if (img.dataset.src && !img.src) {
img.src = img.dataset.src;
}
// 如果直接是src属性
else if (!img.src && img.hasAttribute('src')) {
// 不做处理,因为已经有src属性
}
}
});
}
// 初始加载可视区域内的图片
document.addEventListener('DOMContentLoaded', lazyLoadImages);
// 滚动时加载
window.addEventListener('scroll', lazyLoadImages);
window.addEventListener('resize', lazyLoadImages);
首先引入lazysizes库:
<script src="https://cdnjs.cloudflare.com/ajax/libs/lazysizes/5.3.2/lazysizes.min.js" async></script>
然后修改图片标记(无需修改已有HTML,通过JS自动处理):
document.addEventListener('DOMContentLoaded', function() {
const images = document.querySelectorAll('article img:not([loading])');
images.forEach(img => {
if (!img.classList.contains('lazyload')) {
// 如果图片已经有src属性
if (img.src) {
img.dataset.src = img.src;
img.removeAttribute('src');
}
img.classList.add('lazyload');
}
});
});
占位符处理:为异步加载的图片添加占位样式,避免布局跳动
img[data-src] {
background: #f1f1f1;
min-height: 100px; /* 根据你的设计调整 */
}
2.错误处理:添加图片加载失败的回调
images.forEach(img => {
img.onerror = function() {
this.style.display = 'none';
// 或者显示一个错误占位图
};
});
3.优先级处理:首屏图片不要延迟加载
// 获取首屏内的图片并立即加载
const firstScreenImages = document.querySelectorAll('article img:not([loading])');
firstScreenImages.forEach(img => {
const rect = img.getBoundingClientRect();
if (rect.top < window.innerHeight && rect.bottom > 0) {
if (img.dataset.src) img.src = img.dataset.src;
}
});
4.SEO友好:确保搜索引擎能抓取到图片内容
<!-- 使用noscript标签为禁用JS的环境提供备用 -->
<noscript>
<img src="real-image.jpg" alt="描述文本">
</noscript>
选择哪种方法取决于你的项目需求:
现代浏览器项目:方法1或方法2
需要广泛兼容性:方法3或方法4
复杂项目:推荐使用lazysizes库