Vue 插件 vue-lazyload 在加载alicdn图片404时无法正确加载error图片

阅读 (981)
这是因为https://img.alicdn.com加载图片即便是404,却依然返回了1x1的像素点,这样一来,虽然图片的状态虽然是404了,但 vue-lazyload成功加载了图片,lazy的值是loaded,由于插件原码中未对图片尺寸进行判断(也可以理解,不判断也正常)

如果因为插件没有对图片尺寸进行判断,而强行修改插件,显然是不合适的,万一后续插件更新升级,那一旦忘了修改过插件源码就打包上传了,那势必会影响线上代码造成额外的维护成本

我们可以在插件的回调函数中来对图片的尺寸进行判断并进行相关处理

在main.js中加载使用插件时就可以设置adapter

官方插件地址:https://github.com/hilongjw/vue-lazyload

里面有相关回调函数的使用说明,我这里用到了以下方法:

adapter dynamically modify the attribute of element { } Element Adapter

官方示例:

Vue.use(vueLazy, {
    adapter: {
        loaded ({ bindType, el, naturalHeight, naturalWidth, $parent, src, loading, error, Init }) {
            // do something here
            // example for call LoadedHandler
            LoadedHandler(el)
        },
        loading (listender, Init) {
            console.log('loading')
        },
        error (listender, Init) {
            console.log('error')
        }
    }
})

可以看到adapter 里有对loaded、loading、error三个加载状态进行了回调,上面已经说过了,因为阿里的图片404的状态下依然返回了1x1这样一个像素的图片,造成插件即便是这种情况下lazy的状态值依然是loaded,那我们只要在loaded中对图片的naturalHeightnaturalWidth两个值按需判断即可,我这里只要判断图片宽高同时小于等于1,就认为图片加载失败,然后对该元素手动重新设置lazy状态和图片地址

Vue.use(VueLazyload, {
  error: '../static/images/image-error.png',
  loading: '../static/images/loading.gif',
  adapter: {
    loaded ({ bindType, el, naturalHeight, naturalWidth, $parent, src, loading, error, Init }) {
      // 由于阿里cdn的图片在404状态下,依然返回了1x1像素,这里进行图片大小错误判断
      if (naturalHeight <= 1 && naturalWidth <= 1) {
        $(el).attr('lazy', 'error') // 我这里用了$符号是我另外加载了jQuery插件
        $(el).attr('src', '/static/images/image-error.png')
      }
    },
    loading (listender, Init) {
      console.log('loading')
    },
    error (listender, Init) {
      console.log('error')
    }
  }
})

更新日志:上面的方法在路由跳转后,再重新回到刚刚的页面,图片的naturalHeight和naturalWidth无法正常获取,值都是0,暂时没有找到修复方案

后来换了elementui 自带的 图片lazyload:

<el-image :src="item.miniPictUrl ? item.miniPictUrl : item.pictUrl" :lazy="true" @load="handleLoaded">
  <div slot="placeholder" class="image-slot">
    <img src="/static/images/loading.gif">
  </div>
  <div slot="error" class="image-slot">
    <img src="/static/images/image-error.png">
  </div>
</el-image>

在methods: 中增加事件

handleLoaded (e) {
  if (e.currentTarget.naturalWidth <= 1 && e.currentTarget.naturalHeight <= 1) {
    var src = $(e.currentTarget).attr('src')
    $(e.currentTarget).attr('data-src', src) // 这里记录一下原始加载的图片src,方便调试
    $(e.currentTarget).attr('src', '/static/images/image-error.png')
  }
}

希望能帮到同样被坑的你

更新于:2019-12-11 11:33:18
返回顶部