loading="lazy"不提供加载完成事件监听,仅控制请求时机;需配合img.onload(确保src为真实url)捕获加载完成,用intersectionobserver近似监听加载开始。

loading="lazy"本身不提供加载完成事件监听
浏览器对loading="lazy"的实现是黑盒化的:它控制请求发起时机,但不暴露“开始加载”或“加载完成”的钩子。你无法通过onload、onerror或IntersectionObserver直接捕获“浏览器决定要加载这张图了”这个动作——因为onload触发时请求早已发出,而IntersectionObserver只告诉你“它快进来了”,不是“它正在下载”。
想监控加载完成,必须用img.onload + 手动控制src
原生loading="lazy"和onload能共存,但有个关键前提:src必须真实存在且有效。如果用了loading="lazy"却把src设为空或占位图,onload就永远不会触发。
- 正确做法:保留真实
src,仅加loading="lazy",然后监听onload——这样能捕获浏览器最终加载成功的时刻 - 错误做法:
<img src="placeholder.svg" loading="lazy">→ 此时onload只对占位图触发,和真实图片无关 - 若必须用
data-src(比如为兼容老浏览器),那就别用loading="lazy",改用IntersectionObserver手动赋值src,再在赋值后立刻绑定onload
如何区分“加载开始”和“加载完成”
严格来说,没有标准 API 能监听“加载开始”。但你可以用以下组合逼近:
-
IntersectionObserver回调中调用img.src = img.dataset.src的那一刻,可视为“加载开始”的近似时间点(实际网络请求通常在此后几毫秒内发出) -
img.onload是唯一可靠的“加载完成”信号,但需确保src已被赋真实值,且图片非404 - 别依赖
img.naturalWidth > 0判断是否加载完——它可能在解码中就返回非零值,不可靠 - 如需失败监控,必须同时监听
onerror,并注意:404、跨域拒绝、MIME类型错误都会触发它
容易被忽略的兼容性细节
某些场景下onload会静默失效:
- Safari 15.4–16.4 对
loading="lazy"图片的onload支持不稳定,尤其在src动态变更后;稳妥做法是监听前先检查img.complete === true,若为真则立即执行回调 - 如果图片被
display: none包裹,Chrome 和 Firefox 仍会触发onload,但 Safari 可能延迟到元素变为可见后才触发 - 服务端渲染(SSR)页面中,首屏图片即使带
loading="lazy"也会立即加载,此时onload会在 DOM ready 前就触发,需在document.addEventListener('DOMContentLoaded', ...)里注册监听,或用img.decode()确保解码完成
loading="lazy"的“加载过程”幻想——它只管发请求,不管后续。你要的“何时加载”,本质是“何时赋值src”+“src何时加载完”,这两步都得自己握在手里。前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











