onerror需结合路径校验、this.onerror=null和base64兜底图才可靠;常见失效因fallback路径404触发二次错误,浏览器禁止重复执行;动态创建img须插入前手动绑定onerror,且fallback优先用本地svg或base64。

直接用 onerror 属性最简单,但不加防重逻辑会卡死页面;真正可靠的 fallback 要结合路径校验、this.onerror = null 和 base64 兜底图三者缺一不可。
onerror 为什么经常不显示占位图
最常见原因是 fallback 图片路径也 404,触发第二次错误,而浏览器规范禁止重复执行 onerror —— 看似写了 onerror="this.src='fallback.jpg'",实际根本不会生效。
- 必须在赋值前清除自身:写成
onerror="this.onerror=null;this.src='/assets/placeholder.svg'" - fallback 路径要用绝对路径(以
/开头)或明确可访问的相对路径,避免又掉进相对路径陷阱 - SVG 占位图比 JPG/PNG 更稳:无渲染失败风险、体积小、天然透明背景
-
alt属性不能省,它是图片加载失败时唯一能展示的文案,也是无障碍基础
动态创建的 img 元素怎么绑定 onerror
内联写法对 JS 动态插入的 <img> 失效——DOM 插入前没机会解析 HTML 属性,错误可能在 onerror 绑定前就已抛出。
- 必须在插入 DOM 前手动赋值:
img.onerror = () => { img.src = '/assets/placeholder.svg'; img.onerror = null; }; - 不要用字符串拼接 HTML,改用
document.createElement('img')+ 属性设置 - 如果用模板字符串生成 HTML,需额外加一层 JS 检查:插入后遍历所有新
img,补上onerror
onerror 根本不触发的几种情况
它只响应网络层失败(404/403/500),对以下场景完全静默:
-
src是空字符串、纯空格或data:协议但内容损坏——浏览器压根不发请求 - CORS 阻止(比如跨域图没配
crossorigin)——控制台报错,但onerror不触发 - 服务器返回 200 状态码的兜底图(如某些 CDN 的“图片不存在”占位图)——浏览器认为“成功加载”
- 图片文件头正常但数据块损坏(JPEG 解析失败)——可用
img.naturalWidth === 0辅助判断,但需额外监听load后检查
更可靠替代方案:CSS :has() + background fallback
现代浏览器(Chrome 105+、Safari 15.4+)可用纯 CSS 规避 JS 时机问题,不依赖网络请求,也不怕 onerror 失效。
img {
background: #f0f0f0 url(/assets/placeholder.svg) center/contain no-repeat;
}
img:has(:not([src])) {
background-color: #e0e0e0;
}
img[src^="data:"]:not([src*="base64"]) {
background-color: #ddd;
}
注意::has() 目前只能检测 src 缺失或非法协议,无法识别真实 404;真正要覆盖全部失败场景,仍得靠 JS 补充。
最容易被忽略的是 fallback 图片自身的可靠性——别用另一个网络请求兜底,优先选 inline base64 或本地 SVG;还有就是 file:// 协议下所有图片加载都会被拦,调试时必须起本地 HTTP 服务,否则再好的 onerror 也白搭。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











