图片加载失败时需用onerror钩子手动控制换源,限制重试次数(如最多2次)、避免死循环,并按原始URL→CDN备份→本地路径→SVG占位图顺序降级,第3次直接设透明图并移除onerror。

图片加载失败时怎么自动换源
浏览器原生不提供「图片加载失败后自动尝试下一张」的能力,onerror 是唯一可依赖的钩子,但它只能触发一次,且不能阻止后续重复调用——如果换源后又失败,会无限循环。必须手动控制重试次数和兜底逻辑。
- 给
<img>添加onerror="handleImageError(this)",并在 JS 中定义handleImageError - 在函数里先检查当前
src是否已是备用地址(比如含"fallback"或已带retry=1),避免死循环 - 按顺序尝试:原始 URL → CDN 备份 → 本地相对路径 → 占位图(如
data:image/svg+xml;base64,...) - 最多重试 2 次,第 3 次直接设为透明占位图并移除
onerror,防止反复触发
如何用 data-src 延迟加载 + 自动降级组合使用
懒加载场景下,src 初始为空或占位图,真实地址存在 data-src;此时降级逻辑要覆盖「首次加载」和「换源重试」两个阶段,不能只监听 src 变化。
- 把真实地址统一存在
dataset.src,首次加载时赋值给src,失败后从dataset.fallback、dataset.backup等字段取备用地址 - 每次换源前,用
element.dataset.retryCount = (parseInt(element.dataset.retryCount) || 0) + 1记录次数 - 推荐 fallback 字段存数组 JSON 字符串:
data-fallback='["//cdn2.example.com/xx.jpg", "/img/xx-local.png"]',JS 里JSON.parse()取值 - 注意:Safari 对
data-属性大小写不敏感,但解析 JSON 时引号必须是双引号
为什么 img.onerror 在某些 CDN 下不触发
不是所有 404 都会触发 onerror:当服务器返回 200 状态码但响应体为空、或返回 HTML 错误页(如 Cloudflare 的 502 页面)、或跨域资源未配 CORS 且图片被拦截时,onerror 静默失效。
将调研报告、方案对比、数据分析、需求梳理、会议纪要、设计说明、代码评审、学习笔记等任务产物输出为可在浏览器直接打开的单文件 HTML,替代 Markdown 作为最终交付物。Markdown 在信息密度、视觉清晰度和可分享性上已跟不上 AI 产物的丰富度,HTML 能同时承载排版、表格、SVG 等。
- 验证方式:打开 DevTools → Network → 找对应图片请求,看 status 和 response type;若 status 是 200 但 preview 为空,说明服务端没返回有效图片
- 临时对策:用
fetch()预检 URL(需同域或 CORS 开启),根据response.ok和response.headers.get('content-type')?.includes('image')判断是否可用 - 更稳方案:服务端统一返回标准错误图(如 1×1 transparent PNG),前端通过
canvas读取像素判断是否全透明,再决定是否降级(适合关键图片)
SVG 占位图 inline 写法要注意什么
用 data:image/svg+xml;base64 替代外部占位图,能彻底规避网络请求失败风险,但编码和特殊字符容易出错。
立即学习“前端免费学习笔记(深入)”;
- SVG 必须去掉换行和多余空格,再用
btoa()编码;推荐先写好 SVG 字符串,用encodeURIComponent(svgStr).replace(/%([0-9A-F]{2})/g, (match, p1) => String.fromCharCode('0x' + p1))转义,再 base64 - 常见翻车点:SVG 中含
<title>或注释,会导致 base64 后解析失败;<svg>标签必须带xmlns属性:<svg xmlns="http://www.w3.org/2000/svg"> - 简单占位图够用就别折腾:例如灰色方块可直接用
data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='100' height='100' viewBox='0 0 100 100'%3E%3Crect width='100' height='100' fill='%23ddd'/%3E%3C/svg%3E
onerror 触发但无后续请求,大概率是服务端返回了伪装成图片的 HTML 页面。


















