自定義vueUI組件庫(二)替代傳統img標籤,實現圖片懶加載

dht-img 替代原有的img標籤功能,組件本身的寬高都由最外層容器所決定,支持圖片加載失敗處理 src String     src本地圖片需要require  
fit String cover    
alt String 加載失敗   當最終還是加載失敗的時候
error-src String     輸入的情況下載alt之前,如果錯
誤處理圖片能加載成功則加載錯誤
成功圖片
lazy Boolean FALSE     是否啓用圖片懶加載

 

這個功能比較耗時,但是也算順利寫出來了,代碼挺low的,並且也沒有定義加載過程中圖片或者文字代替。但是這樣我也比較滿意了。

並且增加了圖片懶加載,懶加載的本身是直接支持單個元素的。只有在頁面當中展示了纔會加載圖片。

代碼部分

<template>
  <div class="dht-Image" @click="lazyImg">
    <img
      ref="dht_img"
      class="dht-showimg"
      :style="{ objectFit: fit }"
      v-if="isload"
      :src="lazy === true ? lazyList.img : src"
      :alt="alt"
      @error="imgErr"
      @load="imgSuccess"
    />
    <div v-else class="dht-errImgInfo">
      <img
        ref="dht_img2"
        class="dht-showimg"
        :style="{ objectFit: fit }"
        v-if="errload"
        :src="lazy === true ? lazyList.errimg : errorSrc"
        :alt="alt"
        @error="imgErr2"
        @load="imgSuccess2"
      />
      <span v-else>{{ alt }}</span>
    </div>
  </div>
</template>

<script>
export default {
  name: "dhtImg",
  props: {
    lazy: {
      type: Boolean,
      default: false
    },
    src: {
      type: String,
      default: ""
    },
    //最終失敗提示
    alt: {
      type: String,
      default: "圖片加載中……"
    },
    //錯誤圖片
    errorSrc: {
      type: String,
      default: ""
    },
    fit: {
      type: String,
      default: "cover"
    }
  },
  filters: {},
  watch: {
    //需要實時監聽數據變化,否則單純數據變化,不會重新顯示圖片
    src() {
      this.isload = true;
    },
    errorSrc() {
      this.errload = true;
    }
  },
  data() {
    return {
      //圖片是否加載成功
      isload: true,
      //錯誤圖片是否加載成功
      errload: true,
      //計時器
      time: null,
      //懶加載圖片展處
      lazyList: {
        img: "",
        errimg: ""
      }
    };
  },
  beforeCreate() {},
  created() {},
  beforeMount() {},
  mounted() {
    //是否懶加載展示圖片
    this.lazy && this.lazyImg();
  },
  methods: {
    //懶加載函數
    lazyImg() {
      //啓動之前先清理之前的定時器
      clearInterval(this.time);
      //獲得當前元素
      let dom = this.$refs.dht_img;
      //判斷元素是否顯示
      let isElementInViewport = el => {
        var rect = el.getBoundingClientRect();
        return (
          rect.top >= 0 &&
          rect.left >= 0 &&
          rect.bottom <=
            (window.innerHeight || document.documentElement.clientHeight) &&
          rect.right <=
            (window.innerWidth || document.documentElement.clientWidth)
        );
      };
      this.time = setInterval(() => {
        //當元素顯示則停止計時器
        isElementInViewport(dom) && this.stopLazyImg();
      }, 1000);
    },
    //停止計時器,讓圖片顯示
    stopLazyImg() {
      clearInterval(this.time);
      //console.log("該展示圖片了,並且定時器也要停止。");
      //注意讓元素圖片狀態重新變化
      this.isload = true;
      this.errload = true;
      this.lazyList = {
        img: this.src,
        errimg: this.errorSrc
      };
    },
    //img成功
    imgSuccess() {
      this.isload = true;
    },
    //img錯誤加載判斷
    imgErr() {
      let img = this.$refs.dht_img;
      img ? (img.onerror = null) : ""; //控制不要一直跳動
      this.isload = false;
    },
    imgSuccess2() {
      this.errload = true;
    },
    imgErr2() {
      let img2 = this.$refs.dht_img2;
      img2 ? (img2.onerror = null) : ""; //控制不要一直跳動
      this.errload = false;
    }
  }
};
</script>

<style lang="scss">
@import "../style/common/let_style";
.dht-Image {
  width: 100%;
  height: 100%;
  .dht-showimg {
    @extend .dht-Image;
  }
  .dht-errImgInfo {
    width: 100%;
    height: 100%;
    font-size: 12px;
    color: $font_info;
    display: flex;
    align-items: center;
    justify-content: center;
  }
}
</style>

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章