onerror无限循环的根本原因是备用图也加载失败,导致反复触发;必须写成this.src='fallback'; this.onerror=null,且优先使用base64 SVG或绝对路径确保fallback可达。

onerror 为什么一写就无限循环
根本原因不是代码写错了,而是备用图本身也加载失败:浏览器把 this.src 换成新地址后,立刻发起第二次请求;如果这个新地址返回 404 或网络异常,onerror 再次触发,又换 src……如此反复。内存飙升、标签页无响应都是真实后果。
关键点在于:onerror 不会自动判断“这次换的图是不是已经试过了”,它只认“请求失败”这一个信号。
- 绝对不能只写
onerror="this.src='fallback.png'" - 必须紧接
this.onerror=null,且顺序不能颠倒 - 推荐写法:
onerror="this.src='/assets/placeholder.svg'; this.onerror=null;" - 如果 fallback 图路径不可靠(比如相对路径、拼写错误、CDN 故障),整个降级链就断了,用户看到白屏或裂图
预览场景下 fallback 图必须零路径风险
图片预览通常依赖动态生成的 URL(如用户上传后返回的临时链接),这类链接生命周期短、权限敏感、易过期。一旦预览图 404,fallback 若还走相对路径或未托管的本地文件,大概率跟着一起 404。
真正可用的 fallback 只有两类:
立即学习“前端免费学习笔记(深入)”;
-
data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMzAiIGhlaWdodD0iMzAiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PHJlY3Qgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgZmlsbD0iI2ZmZiIvPjwvc3ZnPg==—— 内联 SVG,无请求、无跨域、无路径解析,体积小(约 100 字节) - 绝对路径指向 CDN 托管的静态占位图,如
/assets/preview-fallback.jpg,且该路径需在 Nginx / Apache 中显式配置为可匿名访问
别用 ./fallback.png 或 ../images/missing.jpg —— 预览页路由层级一变,路径就失效。
动态插入的预览图 onerror 必须提前绑定
很多预览功能是 JS 动态创建 <img> 并插入 DOM 的(比如点击缩略图后弹出大图)。这时如果写成:
将 Markdown 文章转换为微信公众号兼容的纯 HTML 格式。当用户要求"转成微信格式"、"生成公众号文章 HTML"、"排版到微信草稿箱"、"微信粘贴格式"时触发。输出带内联样式的纯 HTML,微信编辑器可直接渲染,无需额外适配。支持标题、段落、列表、粗体、行内代码、表格、引用块、代码块、配图的完整转换。
<div id="preview"></div>
再在 JS 里:
const img = document.createElement('img');<br>img.src = userPreviewUrl;<br>previewEl.appendChild(img);<br>// ❌ 错误:此时 onerror 已错过首次加载时机
正确做法是绑定事件在插入前:
const img = document.createElement('img');<br>img.src = userPreviewUrl;<br>img.onerror = function() {<br> this.src = 'data:image/svg+xml;base64,...';<br> this.onerror = null;<br>};<br>previewEl.appendChild(img);
注意:内联属性写法(onerror="...")对动态创建的元素无效,必须用 JS 属性赋值或 addEventListener,但后者在 Safari 旧版中兼容性差,优先用前者。
框架中预览组件如何避免渲染循环
Vue 或 React 里直接改 this.src 容易触发响应式更新或重复渲染。例如 Vue 模板中写:
<img :src="previewUrl" @error="previewUrl = fallbackUrl" />
会导致 previewUrl 改变 → 组件重渲染 → <img> 重新挂载 → 再次尝试加载原 URL → 可能再次触发 error。
安全做法是绕过响应式,直操作 DOM:
- Vue:
@error.once+ref,在回调里用this.$refs.img.src = fallback - React:在
onError回调中先判断e.target.src !== fallbackUrl,再赋值 - 两者都应预加载 fallback 图:
new Image().src = fallbackUrl,防止 fallback 时出现空白延迟
最常被忽略的一点:预览图的 alt 文本必须描述内容(如“用户上传的合同扫描件”),而不是“图片加载失败”。语义和降级逻辑要各管各的。


















