onerror无限死循环必现,因备用图失败会持续触发;必须写成onerror="this.src='/img/placeholder.svg'; this.onerror=null;",用绝对路径或base64确保可达,且解绑必须紧随赋值后。

onerror 无限死循环不是偶发 bug,而是没写对就必现的问题——只要备用图也加载失败,浏览器就会持续触发 onerror,直到内存耗尽或标签页卡死。
为什么onerror="this.src='fallback.jpg'"一定卡死?
这行代码本身没有语法错误,但它漏掉了最关键的防护动作:this.onerror=null。浏览器在替换 src 后会立刻发起新请求;如果 fallback 路径返回 404、CORS 拒绝或路径解析错误(比如相对路径被 base URL 干扰),就会再次进入 onerror,形成递归调用。
常见错误现象包括:页面无响应、DevTools 内存曲线陡升、控制台反复出现同一条资源加载失败日志。
- 备用图路径必须是绝对路径(如
/img/placeholder.svg)或已验证可用的 base64(如data:image/svg+xml;base64,PHN2Zy...) - 不能依赖相对路径,尤其在 SPA 路由嵌套较深时,
./fallback.png很可能解析成 404 -
this.onerror=null必须紧跟在this.src=...后面,且用分号隔开;顺序颠倒或漏掉分号都会失效
可靠写法只有这一种:onerror="this.src='/img/placeholder.svg'; this.onerror=null;"
这是目前所有主流浏览器(Chrome、Firefox、Safari、Edge)都稳定支持的最小闭环方案。它不依赖 JS 初始化时机,不引入额外变量,也不需要框架适配。
关键点在于“原子性”:一次赋值 + 一次解绑,中间不穿插任何可能出错的逻辑。
- 示例中
/img/placeholder.svg是绝对路径,确保无论当前页面 URL 是什么,都能正确定位 - 推荐用轻量 SVG 占位图(
- 不要写成
onerror="this.src='fallback.jpg'; this.onerror = null"(少分号),也不要写成onerror="this.onerror=null; this.src='...'"(顺序错)
动态插入的 ![]()
怎么提前绑定?
用 JS 创建并插入图片时,onerror 属性必须在元素插入 DOM 前设置完成。否则,若网络极慢或资源立即失败,事件可能来不及绑定就已触发。
正确做法是显式赋值 onerror 函数,而非仅设字符串属性:
const img = document.createElement('img');
img.src = 'user-avatar.webp';
img.onerror = function() {
if (!this.dataset.handled) {
this.dataset.handled = '1';
this.src = '/img/avatar-fallback.svg';
}
};
document.body.appendChild(img);
这里用 dataset.handled 替代 this.onerror=null,是为了兼容某些极端场景(如 fallback 图被缓存但内容损坏,导致 naturalWidth === 0)。但日常使用仍优先推荐内联字符串写法,更轻、更可控。
哪些情况 onerror 根本不会触发?
别以为写了 onerror 就万事大吉。它只响应网络层失败(HTTP 状态非 2xx、连接超时、DNS 失败等),对以下情况完全静默:
-
src为空字符串、undefined或纯空格——浏览器根本不发请求 - CORS 阻塞(跨域图片未加
crossorigin属性)——控制台报错,但onerror不触发 - 服务器返回 200 状态码的兜底页(如 CDN 的“图片不存在”HTML 页面)——浏览器认为加载成功
- 图片文件头正常但数据损坏(JPEG 数据块断裂)——需额外用
img.naturalWidth === 0检测
真正健壮的降级不是靠一个 onerror 打天下,而是分层控制:onerror 拦网络失败、 保格式兼容、src 本身指向高概率可用资源——三者缺一不可。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











