问题

我们在用 uni-app 开发前端时,经常会用到 image 图片组件,有时图片比较大、网络差或者图片资源已经不存在,就会导致 image 无法显示图片,而呈现出来空白,影响用户体验。

解决

通过查看 image 组件的文档,发现里面有以下事件供使用:

属性名类型默认值说明平台差异说明
@errorHandleEvent 当错误发生时,发布到 AppService 的事件名,事件对象event.detail = {errMsg: 'something wrong'}
@loadHandleEvent 当图片载入完毕时,发布到 AppService 的事件名,事件对象event.detail = {height:'图片高度px', width:'图片宽度px'}

从文档得到启发,我们可以在 image 图片加载完成之前显示一张默认图片,图片加载发生错误的时候显示错误图片(当然也可以用默认图片),具体实现方式如下:

HTML 代码:

<view v-for="(item, index) in list" :key="index">
    <image v-show="item.imgLoaded" :src="item.logo" mode="aspectFit" @error="onErrorImg(item)" @load="onSuccessImg(item)"/>
    <image v-show="!item.imgLoaded" src="/static/images/login-grey.png" mode="aspectFit"/>
</view>

JS 代码:

onSuccessImg(item) {
    this.$set(item, 'imgLoaded', true)
},
onErrorImg(item) {
    this.$set(item, 'imgLoaded', false)
}

注意:此处使用的事件传入的参数需要传入 item 对象,并通过 $set 强制更新视图。

上述方式,如果图片非常多,是不是每个 image 组件都要写这些代码,会不会很繁杂?当然还可以进一步优化!比如通过组件化将该实现方式再包一层当新的组件来使用。这里就不做展开,留给大家动手实现。