onerror对script/link/img有效因其有明确加载生命周期,而CSS background-image属样式计算阶段,不走资源加载管道,故不触发;需改用img标签或fetch主动检测。

onerror 事件为什么对 script/link/img 有效但对 CSS background-image 无效
浏览器只对显式声明的外部资源标签(<script>、<link rel="stylesheet">、<img>、<video>)触发 onerror,因为它们有明确的加载生命周期。CSS 中通过 background-image: url(...) 加载的图片属于样式计算阶段行为,不走资源加载管道,因此 onerror 完全不触发。
常见错误现象:给一个 div 写了 background-image,路径错了却没任何回调,控制台只有 404,页面直接空白或布局错乱。
- 必须改用
<img>标签 +onerror替代背景图,才能获得可监听的失败信号 - 若坚持用 background-image,只能靠 JS 主动 fetch 检查 URL 可达性(注意 CORS 限制),或服务端返回占位图(如 Nginx 配置 404 返回
/placeholder.png?text=bg+missing) -
<link>的onerror在旧版 Safari(≤15.6)中不触发,需 fallback 到轮询document.styleSheets[0].cssRules.length是否非零
如何防止 onerror 触发死循环
onerror="this.src='fallback.jpg'" 看似简洁,但一旦 fallback.jpg 也 404,就会无限重试,内存飙升甚至卡死页面。
关键不是“换一个地址”,而是“换一次就停”。防重逻辑必须写死在内联 handler 里,不能依赖外部函数(否则打包压缩可能破坏引用)。
立即学习“前端免费学习笔记(深入)”;
文章转信息图。将文章/笔记转化为手机可读的 HTML 信息图,自动匹配视觉风格。触发场景:文章转图、笔记转图、信息图、转小红书图、做张图、可视化这篇文章、文生图。
- 稳妥写法:
onerror="if (!this.src.includes('fallback')) { this.src = 'fallback.jpg'; this.onerror = null; }" - 动态创建的
<img>必须在插入 DOM 前绑定onerror,否则可能来不及捕获首次加载失败 - 对
<script>和<link>同样适用:替换后立刻清空onerror,避免备用资源再失败时反复执行
全局 error 事件怎么过滤出真正的资源加载失败
window.addEventListener('error', handler, true) 能捕获所有未被 onerror 拦截的资源错误(比如 JS 动态 createElement('img')),但它也会混入 JS 运行时错误、Promise reject 等噪声。
区分核心是判断事件类型和目标元素:
- 资源加载失败是普通
Event,而 JS 错误是ErrorEvent—— 所以先用!(event instanceof ErrorEvent)过滤 - 再检查
event.target.tagName是否为'IMG'、'SCRIPT'、'LINK',排除其他干扰 - 从
event.target.src或event.target.href提取失败路径,配合sessionStorage记录同一 URL 连续失败次数,2 次以上才上报或降级
file:// 协议下资源加载失败的根本原因与绕过方式
双击打开 HTML 文件时,浏览器强制使用 file:// 协议,所有以 / 开头的绝对路径会被解析成系统根目录(如 file:///css/main.css → 实际请求 C:\css\main.css),而非项目目录,导致 100% 404。
这不是路径写错,是协议层硬限制。DevTools Network 面板里看到的红色请求,Request URL 列显示的才是真实路径。
- 开发阶段必须起本地 HTTP 服务:VS Code 安装
ritwickdey.LiveServer插件,右键 →Open with Live Server - 临时调试可用 Chrome 启动参数
--allow-file-access-from-files,但新版已逐步废弃,切勿写进文档或教新人依赖 - 如果必须双击运行(如邮件附件场景),所有资源路径改用相对路径,且确保 HTML 文件不在 C:/ 根目录下(否则
./js/app.js仍可能被解析错)
onerror 解决,得靠分层容错:HTML 层兜底结构,CSS 层保基础布局,JS 层做能力检测后再执行。


















