出现问题的过程

前端在上传图片的时候,需要在项目里面显示出用户上传过后的图片,但是实际中显示的时候,有时正常,有时加载失败同时控制台报 404 错误。在报 404 错误后,复制路径直接访问,却发现能够访问到这个图片,所以这就很奇怪了。

秉着专研主义精神的我,必须要找到原因。于是我在控制台编辑这个图片的路径,先是改为错的路径,html 里会看到图片重新载入,然后加载失败,继续把路径改为正常的,html 重新加载后,显示正常。

我突然想到,既然能够访问到这个图片,说明上传到服务器肯定是成功了,但是前端显示这块肯定有点问题。重点在于:这个情况是偶尔出现的,所以也不是前端的代码出现问题了。

经过我的思考,应该是图片在上传到服务器的过程中,因为网络及其他原因,储存到数据库中的时间有时快有时慢。快的时候,前端展示图片正常,而慢的时候,虽然上传成功了,但是访问其实还是访问不到,所以前端这块就显示 404,但是当你手动复制路径到浏览器查看时,却发现能看到,其实这时数据库中已经存进去了,所以会出现上述的情况。

解决办法

原生的 img 标签里可以使用 onerroronload ,但是经过我的使用后发现不太完美,就算图片加载失败,也会执行onload

在 Vue 中,可以使用 @error@load 方法来完成对图片的监听,这个 error 是图片显是失败时执行,load 是图片加载成功后执行。

代码大概是长这样的:

<img @error="imgError()"  @load="imgLoad()" class="img" />

这里需要注意一下,就是监听函数的时候,需要加上 ()。在 imgError 执行的时候,获取 img 标签,然后让 src 重新加载一下即可。

imgError() {
	let img = document.querySelector('img')
	img.src = 'xxx'
}

这里只是简单的示例,实际中需要考虑到会无限执行的问题,可以添加一个计数器,允许执行到多少之后,就不再执行。加载成功后,清除计数器。

// data
errorNum: 0

// methods
imgError() {
	if(this.errorNum >= 200) return
	
	this.errorNum ++
	// some code
},

imgLoad() {
	this.clearErrorNum()
},

clearErrorNum() {
	this.errorNum = 0
}

这样就表示,当图片加载失败后,去重新加载图片,当重新的次数小于 200 次内,继续重新加载,当大于 200 次后,不再执行里面的代码。
如果加载成功,就清除计数,重 0 开始。

Logo

前往低代码交流专区

更多推荐