侦听 HTML 源中图像加载事件的唯一可靠方法是在 HTML 中指定 onload 处理程序:
<div id="container">
<img onload="imageLoad()" src="..." />
<img onload="imageLoad()" src="..." />
<img onload="imageLoad()" src="..." />
<img onload="imageLoad()" src="..." />
</div>
这是因为在图像标签自己加载(因此它们存在于 DOM 中)之前,您无法将事件处理程序附加到页面 HTML 中的图像。一旦加载了这些图像标签,图像的源就已经被加载,如果它可以快速使用(比如在浏览器缓存中),它可能会在您附加事件处理程序之前被加载。因此,充其量你不能确定它会起作用,最坏的情况是它不会起作用。无论如何,它可能不可靠。
或者,如果您只想知道页面中的所有图像何时加载,您可以对整个文档使用 load 事件。在 jQuery 中,您可以使用 $(window).load(fn) 来做到这一点。
或者,您可以附加加载事件,然后检查是否有任何图像已加载并将其计为已加载。我不确定是否有官方标准方法来查看图像是否已经加载,但我发现如果在 HTML 中没有设置宽度并且.width 属性有一个非零值,则必须加载图像,因为加载图像会导致设置非零宽度值。
您的另一个选择是不将图像放入页面的 HTML 并动态添加它们,您可以在创建图像时分配负载处理程序,然后再分配 .src 属性。
测试问题
为了进一步探索这一点,我在 jsFiddle 中构建了一个测试平台:http://jsfiddle.net/jfriend00/7FjdJ/。它有四个图像,并报告在 $(document).ready() 触发时已经加载了多少图像,并报告有多少图像触发了.load() 事件。结果显示了从一个浏览器到另一个浏览器的行为变化。
在 Chrome 15 中,如果图像已经在缓存中,我不会收到任何加载事件,并且当$(document).ready() 触发时所有四个都已经加载。该行为似乎会根据图像之后页面中的内容量而有所不同。
在 Safari 5 中,我第一次加载页面时,它会报告 4 个加载事件,0 个图像已经加载。我第二次加载页面时,它报告了 0 个加载事件,已经加载了 4 个图像。
在 IE9 中,图像总是看起来已经加载,并且无论是否缓存,都不会触发加载事件。
在 Firefox 7 中,第一次加载页面时,我得到 0 个加载事件和 4 个已经加载的图像。下次我加载页面时,我得到了 4 个加载事件和 4 个已经加载的图像。
另外,由于这是一个时间问题,如果行为取决于图像的大小和加载它们的速度,我也不会感到惊讶,因为缓慢的加载图像可能会导致加载事件延迟到足以被看到。它还可能取决于图像之后页面中要加载多少内容(例如,在触发 document.ready 之前要完成多少工作)。
所以,我的结论是,在图像开始加载后安装 .load() 事件处理程序的行为从一个浏览器到下一个浏览器以及从一种情况到另一种情况是不一致的,因此你不能指望它没有其他缓解这些差异的代码(检查图像是否已加载)。
还有另一种方法。您可以在 DOM 加载后安装事件处理程序,并且在安装事件处理程序时,您可以检查图像是否已加载。这是一种方法:
<div id="container">
<img src="..." />
<img src="..." />
<img src="..." />
<img src="..." />
</div>
<script>
$("#container img").each(function() {
if (this.complete) {
// this image already loaded
// do whatever you would do when it was loaded
} else {
$(this).on('load', function() {
// image now loaded
});
}
});
工作演示:http://jsfiddle.net/jfriend00/6Cq4y/
你会在演示中发现,如果你的浏览器缓存从未见过这个 jsFiddle,那么 if 会显示 4 个加载事件,但如果浏览器缓存已经见过这个 jsFiddle,那么它将没有任何加载事件和所有图像将在您的 javascript 运行时加载,并且会看到它们已加载到代码的 if (this.complete) 分支中。