onerror里直接改this.src常卡死,因为备用图加载失败会再次触发onerror,形成无限循环;必须立即执行this.onerror=null切断事件绑定,否则浏览器反复请求坏图导致内存暴涨、页面卡顿甚至崩溃。

onerror 里直接改 this.src 为什么常卡死
因为备用图本身也加载失败时,onerror 会再次触发,形成无限循环——浏览器反复尝试加载同一张坏图,内存飙升、页面卡顿甚至崩溃。
必须在替换后立刻切断事件绑定:onerror="this.src='default.png'; this.onerror=null;"。漏掉 this.onerror=null 是最常见也最隐蔽的坑。
- 内联写法中引号和分号不能少,否则 JS 解析失败,
onerror静默失效 - 默认图 URL 必须可访问;如果它也 404,事件不会重发,但页面就留白了(无提示、不报错)
- 不要写成
onerror="fallback()"却没定义fallback函数,否则控制台报ReferenceError,事件同样静默
动态创建的 img 元素怎么安全绑定 fallback
JS 动态插入的 <img> 可能还没绑定 onerror 就已触发错误——DOM 插入前就得设好事件,不能等 appendChild 之后再加。
更稳妥的方案是用捕获阶段全局监听:document.addEventListener('error', handler, true)。它对后续所有动态添加的图片天然有效,且能在错误“冒泡前”拦截。
- 务必判断
e.target.tagName === 'IMG',避免把<script></script>或<link>的加载失败也误处理 - 在 handler 里检查
e.target.src !== defaultUrl,防止备用图加载失败后又触发自身 - 提前预加载备用图:
new Image().src = defaultUrl,避免 fallback 时首次加载延迟
路径错误才是 fallback 失效的真正元凶
80% 的“备用图不显示”根本不是 JS 写错了,而是原始 src 或备用图路径本身 404——比如大小写不符(Avatar.jpg vs avatar.jpg)、少写 ./、跨目录没算准层级,或本地双击打开时 file:// 协议导致路径解析失效。
别猜,直接看 Network 面板:筛选 img 请求,看状态码。404 就修路径,403 就挪文件位置,200 但图破就查 MIME 类型或图片是否损坏。
- 相对路径始终以 HTML 文件所在目录为基准,不是编辑器打开位置,也不是项目根目录
- Windows 下拖进 VS Code 生成的路径带
file:///或反斜杠\,必须手动删掉、全换成/ - 本地调试务必启 HTTP 服务(如
python3 -m http.server),file://下路径行为不可靠
CSS background-image 能不能当 fallback 用
不能。写成 background-image: url(broken.jpg), url(default.png) 看似兜底,实则是两图都发请求,浏览器不会因第一张 404 就自动切第二张——它只是叠加渲染,第一张失败就留白或背景色。
更关键的是:它没有语义(alt 文本无效)、不支持懒加载(loading="lazy")、无法响应 srcset、屏幕阅读器读不到,纯属视觉补救,仅适合装饰性背景。
- 真要 CSS 方案,只能用
<div> 包裹 <code><img>,设背景图为默认图,靠图片正常加载来覆盖背景 - 但这样无法感知加载成功与否,也无法提供可访问文本,属于妥协方案,非正解
- 生产环境优先用
onerror+ 可靠路径 +this.onerror=null组合
备用图逻辑看似简单,真正踩坑的永远是路径细节和事件绑定时机——尤其动态插入场景下,
onerror 没绑到 DOM 元素上,或备用图 URL 本身又 404,问题就从“显示异常”变成“完全无声失效”。











