以下代码将为图像元素注册onerror函数
(function() {
var imgElements = document.getElementsByTagName('img');
for(i = 0; i < imgElements.length; i++) {
(function() {
imgElements[i].onerror = function() {
this.src = base_url() + 'assets/images/placeholder.jpg';
}
})();
}
})();
此代码有时仅适用。 (我正在使用铬);如果我按住F5或快速刷新页面,似乎onerror函数没有被执行。
例如:如果我加载页面,然后等待几秒钟,然后再次刷新src将会改变,但不是所有时间。
我认为这是浏览器的某种缓存问题?
更具体地说,如果我按下chrome上的刷新图标,即使突然刷新,一切都会正常工作。
但是,如果我突出显示URL并按回车键,代码最终不会将src更改为我的占位符图像。
你能否告诉我为何会发生这种情况,并提出一种规避这种方法的方法?
答案 0 :(得分:3)
你无法控制事情的时间安排,使你以这种方式可靠地按照你尝试的方式工作。事情的顺序是这样的:
<img>
标记时,会触发加载src
网址的请求。onerror
处理程序。onerror
处理程序。现在,步骤4和5的顺序纯粹与时间相关,并且不在您的控制之下。某些条件可能会导致它按此顺序发生,而某些条件则反转4和5。并且,请记住,一旦您的页面加载一次,其中的一部分可能会被缓存,并且后续加载中的时序可能会有所不同。有些浏览器甚至可以缓存URL当前无法访问的事实,如果它立即再次请求(因此会立即生成响应),可能会避免再次尝试它。
此外,当.src
属性设置为新值时,某些浏览器的行为并不完全正常。从几年前开始,我知道有些浏览器在更改onload
属性并加载新图像时无法可靠地触发.src
事件。 onerror
处理程序也是如此。我的经验是,它们可以在首次加载图像时可靠地工作,但我不确定它们在设置不同的.src
属性时是否可靠。
要拥有一个不会错过的onerror处理程序,必须在设置或解析.src
属性之前将其置于适当的位置。这有两种方法可以做到。
<img>
标记的一部分。<img>
标签(例如,根本没有.src或HTML中没有),然后使用您的javascript,您可以添加onerror处理程序,然后创建图像或设置适当地.src
。关键是必须在以任何方式设置onerror
属性之前安装.src
处理程序。
解决方案#1看起来像这样:
<img src="xxx.jpg" onerror="setErrorImage(this)">
// this function must be in the global scope
function setErrorImage(img) {
// clear error handler so no chance of looping
img.onerror = function() {};
img.src = base_url() + 'assets/images/placeholder.jpg';
}
实施解决方案#2的一种方法如下:
<img data-src="xxx.jpg">
(function() {
function setErrorImage() {
this.removeEventListener("error", setErrorImage);
this.src = base_url() + 'assets/images/placeholder.jpg';
}
var imgElements = document.getElementsByTagName('img');
var img, url;
for (var i = 0; i < imgElements.length; i++) {
img = imgElements[i];
// now that onerror handler is in place, set the .src property
url = img.getAttribute("data-src")
if (!img.src && url) {
img.addEventListener("error", setErrorImage);
img.src = url;
}
}
})();
你可能根本没有HTML中的<img>
标签,并通过javascript动态创建所有标签,确保在.src
属性设置之前安装了onerror处理程序,但是使设计过程更复杂一些。选项#2的上述解决方案通常优于完全在代码中创建图像对象。