JavaScript图片onload事件无法获取真实src属性的问题
问题拆解与解决方案
咱们来一步步搞清楚你遇到的问题:
为什么拿不到img.jpg的加载日志?
核心原因是浏览器预加载和事件绑定的时机不匹配:
- 当浏览器解析到
<img>标签的瞬间,就会立刻发起对img.jpg的请求,这个过程发生在DOMContentLoaded事件触发之前(毕竟DOMContentLoaded要等整个DOM树解析完才会触发)。 - 而你是在
DOMContentLoaded回调里才给图片绑定onload事件,这时候第一次加载img.jpg的过程已经结束了,这个加载的onload事件根本没被监听到,自然不会输出日志。
至于src和currentSrc拿不到原始地址,是因为你修改src的时候,直接覆盖了图片元素的src属性,currentSrc反映的是当前图片实际加载的资源地址,只会显示最后一次加载的img.jpg?0,之前的地址已经被覆盖了。
为什么会重复输出img.jpg?0?
偶尔重复输出大概率和浏览器缓存机制有关:如果img.jpg?0已经被缓存,修改src后浏览器可能会快速完成加载,甚至触发多次onload;或者某些情况下,图片的加载状态发生了多次变化(比如缓存失效又重新加载),也会导致重复日志。
怎么捕获到两次加载的日志?
想要完整拿到两次加载的记录,关键是提前绑定onload事件,别错过第一次加载,这里给你两种可靠的实现方式:
方式1:在图片解析后立刻绑定事件
把绑定事件的代码放在<img>标签后面,这样浏览器解析完图片后马上绑定事件,不会错过第一次加载:
<head> <script> function onLoadImgView() { console.log(this.currentSrc); } </script> </head> <body> <img id="imgElement" src="img.jpg" width="100" height="100" alt="" /> <script> const img = document.getElementById('imgElement'); // 绑定onload事件,这时候图片可能还在加载中 img.onload = onLoadImgView; // 如果图片已经加载完成,手动触发一次onload if (img.complete) { onLoadImgView.call(img); } // 后续修改src let i = 0; document.addEventListener('DOMContentLoaded', () => { img.src = `img.jpg?${i}`; }); </script> </body> </html>
方式2:用MutationObserver监听src变化
如果需要跟踪所有src的修改,包括初始和后续的,可以用MutationObserver来监听属性变化,结合onload事件:
<head> <script> function onLoadImgView() { console.log(this.currentSrc); } document.addEventListener('DOMContentLoaded', () => { const img = document.getElementById('imgElement'); img.onload = onLoadImgView; // 检查图片是否已加载完成 if (img.complete) { onLoadImgView.call(img); } // 监听src属性的变化 const observer = new MutationObserver(mutations => { mutations.forEach(mutation => { if (mutation.attributeName === 'src') { // 每次src变化后重新绑定onload(确保触发) img.onload = onLoadImgView; } }); }); observer.observe(img, { attributes: true }); let i = 0; img.src = `img.jpg?${i}`; }); </script> </head> <body> <img id="imgElement" src="img.jpg" width="100" height="100" alt="" /> </body> </html>
关于“跳过img.jpg直接加载img.jpg?0”的补充
这种情况是浏览器的正常网络行为:如果在第一次请求img.jpg完成前,你就修改了src,浏览器会直接取消之前的请求,转而发起新的img.jpg?0请求,所以只会有后者的日志。这种情况无法强制浏览器完成第一次请求,但你可以监听abort事件来捕获请求被取消的情况:
img.addEventListener('abort', () => { console.log('原始请求被取消:', img.src); });
内容的提问来源于stack exchange,提问作者Reads
相关产品推荐
相关产品推荐

