onerror一写就卡死是因为备用图也404时会无限重试:新src加载失败→再触发onerror→再换src,形成循环,导致内存暴涨或标签页无响应;必须用this.onerror=null手动截断,且顺序不能颠倒。

onerror 为什么一写就卡死
因为备用图也 404 时,onerror会无限重试:新src加载失败 → 再触发onerror → 再换src……最终内存暴涨或标签页无响应。浏览器不会自动阻止,必须手动截断。
常见诱因包括:fallback.png路径写错、相对路径在file://协议下解析失败、CDN 备份地址本身不可达。
-
this.onerror=null必须紧接在this.src=...之后,分号不能少 - 顺序颠倒(比如先
null再赋值)会导致事件丢失,降级失效 - 动态插入的
<img>,onerror必须在appendChild()前绑定,否则首次错误已发生,事件直接丢失
可靠写法只有这一种
内联写法最简稳定结构:
<img src="broken.jpg" onerror="this.onerror=null;this.src='/assets/placeholder.svg'" alt="描述文字">
关键点:
立即学习“前端免费学习笔记(深入)”;
-
this.onerror=null是硬性要求,不是可选项 - 占位图优先用
data:image/svg+xml;base64,...,彻底规避路径和跨域风险 -
alt不能省——它不参与加载逻辑,但提供语义与可访问性兜底 - 所有路径统一用绝对路径(如
/img/logo.png),避免./或../引发解析偏差
动态图片怎么防循环
JS 创建的<img>不能依赖内联onerror,需提前绑定并标记状态:
- 用
dataset打标:img.dataset.retryCount = '0',每次失败递增,超 2 次即设透明图并移除监听 - 检查当前
src是否已是备用地址(如含fallback或retry=1),避免重复切换 - 降级顺序要明确:原始 URL → CDN 备份 → 本地 SVG →
data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==(1px 透明 GIF) - 第 3 次失败后,直接设
img.src = 'data:image/gif;base64,...'; img.onerror = null
CSS 方案能绕过 JS 执行时机问题吗
现代浏览器可用:has()做轻量 fallback,但它不解决真实 404:
img { background: #eee url(/assets/placeholder.svg) no-repeat center / contain; }
img:has(:not([src])) { background-color: #f0f0f0; }
img[src]:not([src^="data:"]):not([src^="http"]):not([src^="/"]) { background-color: #e0e0e0; }
注意:
- 它只对空
src、非法协议(如foo://)有效,无法识别服务器返回的 404 - 真正网络失败仍需 JS 补充,
:has()只是视觉层第一道防线 - Safari 15.4+、Chrome 105+ 支持,老版本必须回退到
onerror逻辑
最易被忽略的是:onerror不响应 CORS 阻塞、MIME 类型不匹配、服务端返回 200 的兜底页——这些场景里,alt才是唯一可见的降级出口。



















