空字符串src=""会触发两次请求:首次按相对路径加载当前页,失败后浏览器重试;规范要求非空值均需解析,故应移除src属性、用data-src暂存或设为透明gif。

src="" 触发两次请求的典型现象
浏览器遇到 src=""(空字符串)时,会按相对路径规则解析为当前页面 URL 的路径部分 + 空段,最终发起一个指向自身 HTML 文件的请求。比如页面地址是 http://localhost/user/profile,<img src=""> 会尝试加载 http://localhost/user/profile —— 这就是第一次“意外请求”。更糟的是,某些浏览器或框架在检测到资源加载失败(如返回 HTML 内容而非图片)后,会自动重试一次,导致 Network 面板中出现两个相同 URL 的 200 请求,Initiator 分别标为 img 和 script 或 parser。
为什么 src="" 不是“不加载”,而是“加载当前页”
这不是 bug,是 HTML 规范明确的行为:src 属性只要存在且非空值(包括 ""、" "、"javascript:void(0)"),浏览器就必须尝试解析并发起请求。空字符串被视作合法相对 URL,解析结果等价于省略 src 但又强制触发加载逻辑。常见误判点:
-
<img src="">和<img>(无 src)行为完全不同:后者根本不会发请求 -
src="undefined"或src="{{url}}"模板未渲染时,实际 DOM 中就是src="undefined",也会触发无效请求 -
src="data:"开头是安全的,但src="data:,"(逗号后为空)仍可能被部分浏览器当作无效 data URL 并 fallback 到当前页
如何安全地“不设置 src”又保持 DOM 结构
核心原则:让元素存在,但不让浏览器触发任何加载。有且仅有以下两种可靠方式:
- 彻底移除
src属性:img.removeAttribute('src')或创建时不设该属性 —— 浏览器完全忽略加载逻辑 - 用
data-src等自定义属性暂存地址,需要时再赋给src:img.src = img.dataset.src,避免提前触发 - 若必须保留空占位(如 SSR 渲染需要),用
src="data:image/gif;base64,R0lGODdhAQABAPAAAP8AAAAAACwAAAAAAQABAAACAkQBADs="(1×1 透明 GIF)—— 它是真实可加载资源,不会 fallback 到当前页
绝对不要写 src="javascript:void(0)" 或 src="#":前者在部分环境触发 CSP 报错,后者在无 hash 的页面中仍会请求当前路径。
模板渲染场景下最容易漏掉的空值检查
尤其在 Django、Vue、React 等模板中,变量未定义或为空时容易产出 src=""。必须在输出前做显式判断:
- Django 模板:
<img src="%7B%7B%20image_url%7Cdefault:''%20%7D%7D">→ 改为<img if image_url src="%7B%7B%20image_url%20%7D%7D" endif> - Vue:
<img :src="url">→ 改为<img :src="url || null">(Vue 会自动跳过 null 值属性) - React JSX:
<img src="%7Burl%7D">→ 改为{url && <img src="%7Burl%7D">}或使用src={url ?? undefined}
注意:undefined 和 null 在 DOM 属性设置中会被自动忽略,而空字符串 "" 会被保留并生效 —— 这个差异是绝大多数重复请求的根源。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











