onerror能捕获img、script、部分浏览器下的link资源加载失败,但不捕获fetch/ajax失败、css 404或跨域script的详细错误;跨域时仅触发事件而无error信息。

onerror 能捕获哪些资源加载失败
onerror 属性最常用于 <img>、<script></script>、<link>(仅部分浏览器支持)等标签,但它**不捕获 fetch/AJAX 请求失败、CSS 文件 404、或跨域 script 的详细错误信息**。浏览器出于安全限制,对跨域脚本只触发 onerror,但不会提供 event.error 或堆栈——你只能知道“坏了”,不知道为什么坏。
-
<img src="broken.jpg" onerror="this.src='fallback.jpg'">是最典型用法,简单直接 -
<script src="vendor.js" onerror="loadFallbackScript()"></script>可用于 CDN 脚本降级,比如切到本地副本 -
<link rel="stylesheet" href="theme.css" onerror="document.body.classList.add('no-theme')">适合做样式加载兜底
onerror 回调函数里 this 指向谁
在内联 onerror 中,this 指向当前 DOM 元素(如 <img>),不是 window。这点和 addEventListener('error') 不同——后者回调中 this 默认是 window,除非显式绑定。
- 写
onerror="this.style.display='none'"是安全的,this就是那个挂掉的图片 - 如果调用外部函数如
onerror="handleImageError(event)",记得在函数里用event.target拿到元素,别依赖this(尤其在严格模式或模块环境下可能出问题) - 避免在
onerror里直接写多行逻辑,可读性差且难调试;封装成函数更可控
为什么 onerror 有时不触发?常见漏掉的点
三个高频原因:路径没发请求、CSP 阻断、或错误发生在非加载阶段。
- src 为空、
src="javascript:void(0)"或值是纯空格,根本不会触发网络请求,onerror自然不执行 - Content-Security-Policy 头禁止了该资源类型(如
img-src 'self'但图片来自外域),浏览器可能静默丢弃请求,不触发onerror -
<script></script>标签内容内联时,onerror无效——它只对src加载的外部脚本起作用 - Vue/React 等框架中动态设置
src,若在onerror触发前就覆盖了原src,可能导致 fallback 被覆盖两次
替代方案:addEventListener('error') 更灵活吗
是的,但要注意事件冒泡限制和监听时机。
-
img.addEventListener('error', handler)可以拿到完整的event对象,包括event.target和部分event.error(仅同域 script) - 它支持移除监听(
removeEventListener),适合组件级生命周期管理 - 必须在元素插入 DOM 前或后立即绑定,否则可能错过错误事件(资源加载极快,异步绑定容易失效)
- 不能捕获已存在的内联
onerror,二者互不影响;混用时注意逻辑重复
onerror 属性足够;需要日志上报、多策略 fallback 或框架集成时,优先选 addEventListener('error')。别忘了检查 CSP 和资源是否真发出了请求——很多“不触发”问题其实卡在第一步。











