onload会失效是因为缓存图片在绑定事件前就已完成加载,必须在设置src前绑定事件;img.complete需结合naturalWidth判断有效性,跨域需设crossOrigin,decode()才能确保真正可渲染。

图片加载完成检测不能只靠 onload,必须结合 img.complete 和 img.naturalWidth 判断是否真能用;否则缓存图片会直接跳过事件,导致逻辑断裂。
为什么 onload 会失效?
浏览器对已缓存的图片可能在你绑定 onload 之前就完成了加载——事件根本不会触发。这不是 bug,是规范行为。
- 必须在设置
img.src之前 绑定onload和onerror - 用
new Image()创建对象比document.createElement('img')更安全,避免意外重排 - 不要把监听写在
src赋值之后,下面这种写法一定出问题:
const img = new Image();
img.src = '/logo.png'; // ❌ 错!此时可能已加载完
img.onload = () => console.log('never fires');
正确顺序是:创建 → 绑定 → 赋值。
img.complete 怎么用才靠谱?
img.complete 是同步属性,能立刻告诉你图片是否“已就绪”,但它不区分成功和损坏。
- 若
img.complete === true且img.naturalWidth > 0→ 加载成功,可直接用 - 若
img.complete === true但img.naturalWidth === 0→ 图片损坏、空文件或 CORS 拦截(检查控制台是否有 “Unable to get image dimensions due to CORS policy”) - 若
img.complete === false→ 必须继续监听onload/onerror
注意:img.complete 不是响应式属性,它只反映绑定时的快照,后续变化不会更新。
生成可在 deepbi 沙箱 iframe 内运行或作为独立文件运行的交互式 HTML 页面,使用 `window.deepbi` JS SDK 实现数据查询、空间管理、文件浏览及用户操作。当用户提出以下需求时启用该能力: - 创建 KPI 仪表盘、数据表格、文件浏览器、成员列表、管理页面; - 明确要求“转成 dhtml”、“转译成 HTML”、“把 XX 页面转成……”、“控制台页面”、“管理后台”、“DeepBI 页面迁移”; - 提及位于 `apps/console/src/featur
跨域图片为啥 naturalWidth 总是 0?
服务端没配 Access-Control-Allow-Origin,即使 onload 触发了,浏览器也会屏蔽尺寸读取,这是安全限制,不是加载失败。
- 前端加
img.crossOrigin = 'anonymous',前提是后端允许该跨域请求 - 不能靠
img.width或offsetWidth替代 —— 它们受 CSS 或 HTML 属性影响,不是原始尺寸 - 如果无法改服务端,只能 fallback 到预设宽高或服务端返回元数据
需要真正“可渲染”怎么办?
onload 只表示解码就绪,大图(尤其 WebP/HEIC)仍可能在首次绘制时卡顿。这时得用 decode()。
-
img.decode()返回 Promise,等待 GPU 解码完成才 resolve - 必须在
onload后调用,否则会 reject - 不支持 IE,现代浏览器基本都 OK;可加 try/catch 降级
img.onload = async () => {
try {
await img.decode(); // ✅ 真正准备好渲染了
document.body.appendChild(img);
} catch (err) {
console.error('Decode failed', err);
}
};
最易被忽略的一点:懒加载场景下,IntersectionObserver + decode() 才能避免滚动时的图像抖动;只靠 onload 还不够。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!










