js如何识别图片加载失败

在做项目过程中遇到图片请求失败的时候,图片区域会出现一个原生的碎片图标,非常影响用户体验。这时需要用一个 broken 的图片去代替它,来提升户体验。要做到这一点,首先要在代码中识别图片加载失败这个事情。那么怎么判断一个图片加载失败了呢?

在 js 中使用 onerror 事件

javascript 给我们提供了一个 onerror 事件,img 标签支持该事件,当装载文档或者图像的过程中发生了错误,就会触发 onerror 事件。
我们可以在这个事件中,定义要替换加载不出来的原图的 broken 图片。

核心代码:

1
2
3
4
5
6
7
// html
<img src="img.png" onerror="myfunction()">

// javascript
myfunction() {
this.src="default.png"
}

注意:
如果 onerror 指定的图片也不存在的话,会出现无限死循环 404. 解决办法是在 js 中添加:

1
2
3
4
5
// javascript
myfunction() {
this.src="./default.png";
this.onerror = null; // 添加这个防止默认图片也不存在而陷入死循环
}

在 Vue 中怎么使用 onerror

1
2
3
4
5
6
7
8
9
10
11
12
13
// vue
<template>
<img :src="item.imgUrl" :onerror="defaultImg">
</template>
<script>
export default {
data () {
return {
defaultImg: 'this.src="./static/images/default.png"'
}
}
}
</script>

番外

有时因为网络比较卡的原因需要多加载几次再判定为是否加载失败。
但是有时是因为网络连接断开而加载失败,需要在网络恢复连接时自动加载图片。
这是就需要知道,js中怎么识别网络断开和连接的,有两个事件:onlineoffline

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
var isOnLine = true;
var eventList = {};
window.addEventListener('offline', function() {
isOnLine = false;
})
window.addEventListener('online', function() {
if(!isOnline) {
isOnLine = true;
reLine(); // 执行重连后要做的事情
}
})
function reLine() {
for(var key in eventList) {
if(!eventList[key]) continue;
var arg = eventList[key].arg;
var thisOnFn = eventList[key].that;
eventList[key].fun.apply(thisOnFn, arg);
eventList[key] = null;
}
}
function offLined(fun, arg, that) {
if(!isOnLine) {
var name = fun.name || '__new';
eventList[name] = {};
eventList[name].fun = fun;
eventList[name].arg = [].slice.call(arg);
eventList[name].that = that;
return true;
}
return false;
}

---

// 重新定义myfunction
myfunction(imgObj, imgSrc, maxErrorNum) {
if(offLined(restImgUrl, arguments, this)) return;
if(maxErrorNum > 0) {
imgObj.onerror = function () {
myFunction(imgObj, imgSrc, maxErrorNum - 1)
}
setTimeout(function() {
imgObj.src = imgSrc;
}, 500)
} else {
imgObj.src = './default.png';
this.onerror = null;
}
}

// 调用
<img src="img.png" onerror="myfunction(this, this.src, 3)">