ImgUploader.vue 3.74 KB
<template>
  <div id="ImgUploader" :class="type">
    <div class="imgItem" v-for="(item, index) in displayList" :key="index" @click="changeImg(index)">
      <img :src="item" alt="">
    </div>
    <div class="imgItem addImg" v-show="imgList.length < limit" @click="addImg">
      <div class="hint">{{hint}}</div>
      <v-icon>add</v-icon>
    </div>
    <input type="file" ref="input" @change="handleChange" :multiple="limit > 1" :accept="accept">
  </div>
</template>

<script>
export default {
  data: () => ({
    imgList: [],
    displayList: [],
    imgIndex: 0,
  }),
  props: {
    limit: {
      type: Number,
      default: 1
    },
    type: {
      type: String,
      default: 'multi'
    },
    hint: {
      type: String,
      default: '',
    },
    accept: {
      type: String,
      default: 'image/png, image/jpeg, image/webp'
    }
  },
  methods: {
    addImg() {
      this.$refs.input.click()
    },
    changeImg(index) {
      console.log(this.imgIndex)
      this.imgIndex = parseInt(index)
      console.log(index)
      this.$refs.input.click()
    },
    handleChange(e) {
      const files = e.target.files;
      if (this.limit === 1) {
        const file = files[0]
        let fr = new FileReader()
        fr.readAsDataURL(file)
        this.imgList[this.imgIndex] = file
        fr.onloadend = (e) => {
          let newList = [].concat(this.displayList)
          newList[0] = e.target.result
          this.displayList = newList
        }
        this.$emit('change', this.imgList)
        return 
      }
      for (let i = 0; i < files.length; i++) {
        if (this.imgList.length < this.limit) {
          const file = files[i]
          let fr = new FileReader()
          fr.readAsDataURL(file)
          this.imgList[this.imgIndex] = file
          fr.onloadend = (e) => {
            let newList = [].concat(this.displayList)
            newList[this.imgIndex] = e.target.result
            this.displayList = newList
            if (this.limit > 1) {
              this.imgIndex = this.imgList.length              
            }
          }
        }
      }
      this.$emit('change', this.imgList)
    },
  }
}
</script>

<style lang="scss" scoped>
  #ImgUploader {
    width: 100%;
    input {
      height: 0;
      width: 0;
    }
    &.multi {
      display: flex;
      justify-content: flex-start;
      align-items: center;
      flex-direction: row;
      flex-wrap: wrap;
      .imgItem {
        width: 5rem;
        height: 5rem;
        margin-right: 0.5rem;
        margin-top: 0.5rem;
        transition: all 0.3s linear;
        text-align: center;        
        img {
          width: auto;
          height: auto;
          max-width: 100%;
          max-height: 100%;
          vertical-align: bottom;
        }
        .icon {
          font-size: 4rem;
        }
        &.addImg {
          border: 1px dashed #979797;
          line-height: 5rem;
          text-align: center;
        }
      }
    }

    &.single {
      width: 100%;
      .imgItem {
        width: 100%;
        height: 11rem;
        box-sizing: border-box;
        margin-top: 0.5rem;
        transition: all 0.3s linear;
        text-align: center;

        img {
          width: auto;
          height: auto;
          max-width: 100%;
          max-height: 100%;
          vertical-align: bottom;
          margin: auto;
        }
        .hint {
          color: #979797;
          font-size: 1.3rem;
          height: 1.3rem;
          line-height: 1.3rem;
          margin-top: 3rem;
        }
        .icon {
          font-size: 4rem;
          color: #979797;
        }
        &.addImg {
          border: 2px dashed #979797;
          line-height: 5rem;
          text-align: center;
          transition: all 0.3s ease-in-out;
        }
      }
    }
  }
</style>