唯一可靠解法是赋值新src后立刻执行this.onerror=null;onerror="this.src='fallback.png'"必卡死,因备用图404会再次触发onerror导致无限循环。

onerror 无限循环不是写法有误,而是没切断事件链——只要备用图也 404,浏览器就会反复加载、反复触发,直到卡死或白屏。唯一可靠解法是赋值新 src 后立刻执行 this.onerror = null。
onerror="this.src='fallback.png'" 为什么必卡死?
这是最典型的错误写法。浏览器行为很明确:图片加载失败 → 触发 onerror → 执行 this.src = 'fallback.png' → 发起新请求 → 若该地址也返回 404 → 再次触发 onerror → 无限递归。
- 内存持续增长,DevTools 可能无响应
- Safari 和旧 Edge 中尤其容易整页冻结
- 控制台未必报错,但 Network 面板能看到重复的 404 请求
- 哪怕只多一个空格或少个分号,
this.onerror=null就不会执行
正确写法必须含绝对路径 + this.onerror=null
关键不是“换图”,而是“换完就退出”。顺序、分号、路径三者缺一不可。
- 绝对路径优先:
onerror="this.src='/assets/placeholder.svg'; this.onerror=null;" - 相对路径风险高:写成
./fallback.png时,base URL 解析可能出错,二次 404 概率大增 - 推荐 base64 SVG 占位图,彻底规避路径问题:
onerror="this.src='data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMzAiIGhlaWdodD0iMzAiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PHJlY3Qgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgZmlsbD0iI2ZmZiIvPjwvc3ZnPg=='; this.onerror=null;" - 不要用
alt当兜底:它不触发加载,也不阻止裂图显示
动态创建的 ![]()
怎么绑定才不丢事件?
JS 创建的图片,onerror 必须在 src 赋值前绑定,且必须在插入 DOM 前完成。否则首次加载失败时事件早已错过。
- ❌ 错误顺序:
const img = new Image(); img.src = url; container.appendChild(img); img.onerror = handler; - ✅ 正确顺序:
const img = new Image(); img.onerror = handler; img.src = url; container.appendChild(img); - 更稳妥做法:用
dataset标记是否已降级,避免多次触发:img.onerror = function() { if (!this.dataset.loaded) { this.dataset.loaded = '1'; this.src = '/fallback.svg'; } }; - 全局监听
document.addEventListener('error', ...)在 Safari 中不捕获图片错误(事件不冒泡),不推荐作为主方案
里的 onerror 容易被忽略的点
不是自动兜底容器。它的作用是格式协商(WebP/AVIF/JPEG),最终 fallback 责任仍在内部的 元素上。
- 如果
的src是空值、相对路径拼错、或指向一个已下线的 CDN 地址,页面就留白 -
加载失败不会自动跳到下一个,也不会触发的onerror—— 它只管自己那条资源链 - 必须确保
的src指向一个高可用地址,比如托管在稳定 CDN 上的占位图,而不是./missing.jpg - 不要把
onerror写在上:它不支持该属性
真正难的不是写对那一行 onerror,而是保证 fallback 图本身 100% 可达——任何一次 404,都会让整个机制崩回原点。base64 SVG 是目前最省心的选择,但要注意 IE11 不支持 data URL 的 src,如需兼容,得单独加判断。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











