图片替换本质是更新img.src属性以触发浏览器重新请求新url并执行完整生命周期事件,需正确处理onerror降级、srcset同步更新及缓存时间戳策略。

图片替换的本质是更新 DOM 中 <img> 元素的 src 属性
不是重新加载整个页面,也不是靠 CSS 切换背景图来“假装”替换——真实场景下(比如头像上传预览、商品图切换、A/B 测试图替换),必须让浏览器重新发起对新 URL 的请求,并触发加载、错误、完成等生命周期事件。直接赋值 img.src = 'new.jpg' 是最轻量且兼容性最好的方式,但要注意它会立刻触发加载,如果新地址 404 或跨域受限,onerror 才是你兜底的关键。
- 避免用
img.setAttribute('src', ...)替代赋值:虽然也能生效,但部分旧版 IE 对动态 setAttribute 的 src 更新响应不一致 - 替换前可先检查
img.src是否已等于目标 URL,避免无谓的重复加载 - 若需保留原图宽高或懒加载属性(如
loading="lazy"),替换时不用动它们,浏览器会自动复用
替换失败时必须监听 onerror 并降级处理
网络抖动、路径写错、CDN 缓存未刷新、CORS 限制都可能导致新 src 加载失败。此时 <img> 会停留在空白或显示浏览器默认缺省图标,用户无法感知问题。你得主动捕获并干预:
- 在替换前就绑定
img.onerror = () => { img.src = '/fallback.png'; },不要等报错再绑 - 避免在
onerror中再次赋值为一个可能也失效的 URL,建议 fallback 图走本地静态路径或 base64 内联小图 - 如果业务允许,可在
onerror中上报错误:例如fetch('/log?img=broken&url=' + encodeURIComponent(img.src))
批量替换时慎用 srcset 和 sizes 的同步更新
当图片支持响应式(即用了 srcset),只改 src 不够——浏览器可能仍按旧的 srcset 规则选图,尤其在窗口 resize 后。正确做法是同时更新三者:
img.src = '/new-small.jpg'; img.srcset = '/new-small.jpg 480w, /new-medium.jpg 768w, /new-large.jpg 1200w'; img.sizes = '(max-width: 480px) 100vw, (max-width: 768px) 50vw, 33vw';
- 如果新图没有对应多尺寸版本,清空
srcset和sizes:设为img.srcset = '',否则浏览器可能忽略你刚设的src - 注意
srcset中的 URL 必须全部可访问,任一链接 404 都可能导致整组失效(取决于浏览器策略) - 现代框架(如 React)中直接操作 DOM 的
srcset要小心:虚拟 DOM diff 可能绕过你的手动更新
服务端返回图片 URL 带时间戳或 hash 时,要理解它的缓存意图
常见做法是后端在图片 URL 后加 ?v=123456 或 ?t=1717023456 来强制绕过 CDN 或浏览器缓存。这本身没问题,但如果你在 JS 中缓存了这个 URL(比如存在变量或 Map 里),下次替换时又用同一个带时间戳的 URL,就失去了“更新”意义。
- 每次替换都应调用后端接口获取最新 URL,而不是复用上次响应里的带参链接
- 如果必须前端生成时间戳,用
Date.now()而非固定值;但更推荐由服务端控制版本,前端只负责消费 - 注意:某些 CDN 对 query 参数不敏感,即使加了
?v=仍可能返回旧缓存——这时需要服务端配合设置Cache-Control: no-cache或使用路径级版本(如/v2/avatar.jpg)
src 字符串,而是你没法预判新地址是否真能被浏览器拉下来、拉下来后会不会被样式挤变形、或者用户正盯着加载中的空白发呆。这些细节没卡准,图片替换就只是个看起来动了的幻觉。前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











