Необходимо создать поля для загрузки изображений с подгрузкой превью на 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}],
}
},
});