小程序图片加载失败自动重试一次方案

1,477 阅读1分钟

小程序的图片组件本身有个加载失败的绑定事件为 binderror,所以本方案就是要在该绑定的事件中做文章。

首先,给图片绑定加载失败事件,wxml 及 js 代码分别如下:

<!-- 普通图片 -->
<image class="full-width" src="{{imgUrl}}" mode="widthFix" binderror="bindImgErr" data-resrc="{{imgUrl}}" data-name="imgUrl" lazy-load="false"></image>
page({
    bindImgErr(e) {
        const { name, resrc } = e.currentTarget.dataset;
        this.setData({
            [name]: resrc
        })
    }
})

以上代码看起来是没问题的,然后实际情况却并不如此。下面简单说下具体碰到的问题:

图片失败后并不会自动重试一次

由于 data-resrc 中的图片地址与 src 的图片地址一致,所以图片并不会自动重试加载。所以要对 resrc 的地址进行加工,如加个参数 t=1

page({
    bindImgErr(e) {
        const { name, resrc } = e.currentTarget.dataset;
        // 只重试一次
        if (!resrc.includes('t=1')) {
            let url = '';
            if (resrc.includes('?')) {
              url = `${resrc}&t=1`;
            } else {
              url = `${resrc}?t=1`;
            }
            this.setData({
              name: url,
            });
        }
    }
})

图片地址

上面示例的图片地址仅仅是我们常见的一种形式,实际情况中,我们可能会遇到图片地址出现在数组,对象等复杂场景,如下:

page({
    data: {
        imgUrl: 'https://xxx.xxx.com',
        imgUrls: ['https://xxx.xxx.com', 'https://xxx.xxx.com', 'https://xxx.xxx.com'],
        product: {
            imgUrl: 'https://xxx.xxx.com',
        }
    }
})

所以还需要对 name 进行进一步处理:

<!-- 普通图片 -->
<image class="full-width" src="{{imgUrl}}" mode="widthFix" binderror="bindImgErr" data-resrc="{{imgUrl}}" data-name="imgUrl" lazy-load="false"></image>

<!-- 数组 -->
<view wx:for="{{imgUrls}}">
    <image class="full-width" src="{{item}}" mode="widthFix" binderror="bindImgErr" data-resrc="{{item}}" data-name="imgUrl[{{index}}]" lazy-load="false"></image>
</view>

<!-- 对象 -->
<image class="full-width" src="{{product.imgUrl}}" mode="widthFix" binderror="bindImgErr" data-resrc="{{product.imgUrl}}" data-name="product.imgUrl" lazy-load="false"></image>
page({
    bindImgErr(e) {
        const { name, resrc } = e.currentTarget.dataset;
        // 只重试一次
        if (!resrc.includes('t=1')) {
            let url = '';
            if (resrc.includes('?')) {
              url = `${resrc}&t=1`;
            } else {
              url = `${resrc}?t=1`;
            }
            this.setData({
              [`${name}`]: url,
            });
        }
    }
})