判断图片加载完成的几种方法
判断图片是否加载完成是前端开发中的常见需求,以下是几种可靠的方法:
1. 使用 onload 和 onerror 事件
javascript
const images = document.querySelectorAll('img');
images.forEach(img => {
// 图片加载成功
img.onload = function() {
console.log(`${img.src} 加载完成`);
};
// 图片加载失败
img.onerror = function() {
console.error(`${img.src} 加载失败`);
};
// 如果图片已经缓存且加载完成
if (img.complete) {
if (img.naturalWidth === 0) {
console.error(`${img.src} 加载失败(缓存)`);
} else {
console.log(`${img.src} 已缓存`);
}
}
});
2. 使用 Promise 判断所有图片
javascript
function imageLoaded(img) {
return new Promise((resolve, reject) => {
if (img.complete) {
return resolve(img);
}
img.onload = () => resolve(img);
img.onerror = () => reject(img);
});
}
// 判断所有图片
Promise.all(
Array.from(document.images).map(img =>
imageLoaded(img).catch(img => img)
)
).then(() => {
console.log('所有图片加载完成(包括失败的)');
});
3. 监听动态添加的图片
javascript
const observer = new MutationObserver(mutations => {
mutations.forEach(mutation => {
mutation.addedNodes.forEach(node => {
if (node.nodeName === 'IMG') {
imageLoaded(node)
.then(() => console.log('动态图片加载完成:', node.src))
.catch(() => console.error('动态图片加载失败:', node.src));
}
});
});
});
observer.observe(document.body, {
childList: true,
subtree: true
});
4. 使用 loading 属性 + IntersectionObserver(懒加载场景)
javascript
const lazyImages = document.querySelectorAll('img[loading="lazy"]');
const io = new IntersectionObserver((entries, observer) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
const img = entry.target;
img.onload = () => {
console.log('懒加载图片完成:', img.src);
observer.unobserve(img);
};
img.onerror = () => {
console.error('懒加载图片失败:', img.src);
observer.unobserve(img);
};
}
});
});
lazyImages.forEach(img => io.observe(img));
5. 检查图片状态综合方法
javascript
function checkImageStatus(imgs) {
return Array.from(imgs).map(img => {
return {
element: img,
loaded: img.complete && img.naturalWidth !== 0,
failed: img.complete && img.naturalWidth === 0,
src: img.src
};
});
}
// 使用示例
const status = checkImageStatus(document.images);
console.table(status);
注意事项
- 缓存图片:已缓存的图片会立即触发
complete属性为true - 跨域问题:如果图片来自不同域且没有 CORS 头,可能无法准确获取
naturalWidth - SVG 图片:某些浏览器对 SVG 的
complete属性支持不一致 - CSS 背景图:上述方法不适用,需使用
window.getComputedStyle()配合其他技巧
性能优化建议
对于大量图片,建议使用批量检测+分片处理:
javascript
async function checkAllImagesLoaded() {
const images = Array.from(document.images);
const BATCH_SIZE = 10;
for (let i = 0; i < images.length; i += BATCH_SIZE) {
const batch = images.slice(i, i + BATCH_SIZE);
await Promise.all(batch.map(img => imageLoaded(img)));
console.log(`已完成 ${Math.min(i + BATCH_SIZE, images.length)}/${images.length}`);
}
console.log('所有图片处理完成');
}
选择适合你场景的方法即可高效判断图片加载状态。
