@pilolin
HTML программист

Как создать набор блоков для загрузки изображений на vue?

Необходимо создать поля для загрузки изображений с подгрузкой превью на vuejs. Ранее в данном проекте был создан компонент для загрузки одного изображения и без функции удаления этого изображения из поля. Сейчас стало необходимо создать набор блоков появляющихся друг за другом при загрузке изображения в предыдущий блок. И дополнительно удаление изображения если было загружено не то что нужно. Весь исходный код представлен ниже, сократил оставив только нужное. Попробовал реализовать самостоятельно но столкнулся с проблемами.

1) если переменная в которой будут храниться изображения будет массивом то при удалении элементы сдвигаются и происходит косяк с отображением новых

2) так же наблюдается косяк переодически с удалением блока

Т.е. сейчас в сторону загрузки изображений все работает, а в обратную нет

фидл для демонстрации работы


Код для наглядности и вдруг если фидл потеряется
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
  <set-imgs
    :name="'instagram-gig-'" 
    :images="images"
    :max-amount="3"
    :count-per-row="3"/>
</div>


Vue.component('input-img', {
  template: `
    <div class="card-input-img" :style="{'padding-top': height}">
      <i 
        class="card-input-img__icon material-icons card-input-img__size_sm"
        :class="{'card-input-img__icon_remove': (hasRemove && img.src)}" 
        v-text="(hasRemove && img.src) ? 'x' : '+'" 
        @click="removeImg"/>
      <img 
        v-if="img.src || background" :src="img.src || background" 
        class="card-input-img__image card-input-img__image_size_cover">
      <input 
        type="file" 
        :name="name"
        accept="image/*"
        @change="fileChangeHandler">
    </div>`,
  props: {
    name: {
      type: String,
      required: true
    },
    height: {
      type: String,
      default: '100%'
    },
    img: {
      type: Object,
      default: null
    },
    background: {
      type: String
    },
    hasRemove: {
      type: Boolean,
      default: true
    }
  },
  data() {
    return {
      newImg: {
        file: null,
        src: null
      },
      firstUpload: true,
    }
  },
  created() {
    this.newImg = this.img
  },
  methods: {
    fileChangeHandler(e) {
      this.newImg.file = e.target.files[0];
      if( this.newImg.file ) {
        let reader = new FileReader();
        reader.onloadend = () => {
          const image  = new Image();
          image.onload = () => {

            this.newImg.src = image.src;

            this.$emit('update:img', this.newImg);
            if(this.firstUpload) {
              this.$emit('first-uploaded', this.newImg);
              this.firstUpload = false;
            }
          }
          image.src = reader.result;
				}
        reader.readAsDataURL(this.newImg.file);
      } 
    },
    removeImg() {
      document.querySelector(`[type="file"][name="${this.name}"]`).value = null;
      this.$emit('remove');
      this.newImg = {
        file: null,
        src: null
      };
      this.firstUpload = true;
    }
  }
});

Vue.component('set-imgs', {
  template: `
    <div class="grid grid_col_3 grid_gap_s">
      <input-img 
        v-for="(image, i) in images"
        :key="i"
        :name="name + i" 
        :background="image.src"
        :img.sync="image" 
        @update:img="image = $event"
        @first-uploaded="addFieldNextImage"
        @remove="removeElem(i)" />
    </div>`,
  props: {
    name: {
      type: String,
      required: true
    },
    img: Object,
    maxAmount: {
      type: Number,
      default: 3,
    },
    countPerRow: {
      type: Number,
      default: 3,
    },
    images: {
      type: Array,
      default: () =>  [{file: null, src: null}]
    }
  },
  methods: {
    addFieldNextImage() {
      if(this.images.length < this.maxAmount) { 
        this.images.push({ file: null, src: null });
      }
    },
    removeElem(i) {
      this.images.splice(i, 1);
    },
  }
});

new Vue({
  el: '#app',
  data() {
    return {
      images: [{file: null, src: null}],
    }
  },
});
  • Вопрос задан
  • 56 просмотров
Решения вопроса 1
0xD34F
@0xD34F Куратор тега JavaScript
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы
19 авг. 2019, в 16:45
100000 руб./за проект
19 авг. 2019, в 15:55
700 руб./в час