1、在拖拽上传图片中使用到transition-group,一般情况下,v-for循环使用Index(索引)作为key值是没毛病的,但是在transition-group就会出现小毛病
<draggable v-model="copySave" group="site" delay="100" @add="changeSave($event, copySave)" class="draggableBox">
<transition-group class="groupBox">
<div class="uploadLi" v-for="(item, index) in copySave" :key="index" @mouseover="showDel5(index)" @mouseleave="notShowDel5">
<img :src="item" alt="" class="imgs">
<span class="delBtn" @click="delImg5(index)" v-show="isShowDel5 == index? true: false">
<a-icon type="delete" />
</span>
<span class="delBtn btnLook" @click="plusImg(item)" v-show="isShowDel5 == index? true: false">
<a-icon type="eye" />
</span>
<span class="imgBg" v-show="isShowDel5 == index? true: false"></span>
</div>
</transition-group>
</draggable>
2、后台直接返回图片的url组成的数据,无其他属性,所以只能这样循环,所以,解决报错,需要手动自己添加id或者其它唯一的属性
getData() {
// 获取父组件的值
this.copySave = [];
this.copySave1 = [];
let saveObj = JSON.parse(JSON.stringify(this.saveImgs));
let arr = saveObj.sitePhotos && saveObj.sitePhotos.length? saveObj.sitePhotos: [];
// 给每个项添加id(因为在transition-group中使用index作为key值是没有达到唯一性的)
arr.map((item, index) => {
// 又因为是动态数据,id也是动态添加,所以加上随机数,这样使的id不会重复(三id,如果你杠,你就是对的)
this.copySave.push({url: item, id: index + Math.floor(Math.random() * 10000)});
})
let arr1 = saveObj.siteRecordPhotos && saveObj.siteRecordPhotos.length? saveObj.siteRecordPhotos: [];
arr1.map((item, index) => {
this.copySave1.push({url: item, id: index + Math.floor(Math.random() * 10000)});
})
// 没修改之前的做法
// this.copySave = saveObj.sitePhotos && saveObj.sitePhotos.length? saveObj.sitePhotos: [];
// this.copySave1 = saveObj.siteRecordPhotos && saveObj.siteRecordPhotos.length? saveObj.siteRecordPhotos: [];
},
3、上传的地方也要做处理哟
async uploadSave(data) {
const formData = new FormData()
formData.append('file', data.file)
this.loadingSave = true
let res = await this.$http(this.$url.ORDER_PHOTO_UPLOAD, 'str', formData)
this.loadingSave = false
if (res.data.code == 0 || res.data.code == 200) {
let imgUrl = res.data.data.fileUrl
this.$message.success('上传成功');
// 判断已有数组长度
if(this.copySave.length == 0) {
// 无数据时,放第一项
this.copySave.push({url: imgUrl, id: 0 + Math.floor(Math.random() * 10000)})
} else {
// 有数据时,放在最后面
this.copySave.push({url: imgUrl, id: this.copySave.length + Math.floor(Math.random() * 10000)})
}
// this.copySave.push(imgUrl)
this.copySave = this.copySave.slice(-3)
}
},
4、key值为id,最后渲染部分修改一下代码
<draggable v-model="copySave" group="site" delay="100" @add="changeSave($event, copySave)" class="draggableBox">
<transition-group class="groupBox">
<div class="uploadLi" v-for="(item, index) in copySave" :key="item.id" @mouseover="showDel5(index)" @mouseleave="notShowDel5">
<img :src="item.url" alt="" class="imgs">
<span class="delBtn" @click="delImg5(index)" v-show="isShowDel5 == index? true: false">
<a-icon type="delete" />
</span>
<span class="delBtn btnLook" @click="plusImg(item.url)" v-show="isShowDel5 == index? true: false">
<a-icon type="eye" />
</span>
<span class="imgBg" v-show="isShowDel5 == index? true: false"></span>
</div>
</transition-group>
</draggable>
5、拿到数据,因为后台需要参数为url组成的数组
// 点击弹窗确认按钮
async handleSave() {
let data = await this.$refs.saveImgs.setImgsList();
if (data.copySave.length > 0 && data.copySave1.length > 0) {
// 后台只需要url组成的数组,不需要其余的参数,所以。。。
let arr = [];
data.copySave.forEach((item, index) => {
arr.push(item.url);
});
this.saveList = arr;
let arr1 = [];
data.copySave1.forEach((item, index) => {
arr1.push(item.url);
});
this.saveList1 = arr1;
this.showSaveMod = false;
// this.saveList = data.copySave
// this.saveList1 = data.copySave1
} else {
return this.$message.error("请至少选择一张图");
}
},
// 请求接口的参数
data.sitePhotos =
this.saveList && this.saveList.length ? this.saveList : [];
data.siteRecordPhotos =
this.saveList1 && this.saveList1.length ? this.saveList1 : [];
let res = await this.$http(
this.$url.ORDER_CONSTRUCTIONSECURE_DETAIL_UPDATE,
"put",
data
);
6、总结:拖拽后,元素的key发生了变化。解决思路:给key值设置一个不会因为位置变化而变化的值, 又因为是动态添加的id值且可能会拖拽到同id的数组,所以为避免出现重复,所以加了随机数.
参考文章:https://blog.csdn.net/qq_38280242/article/details/103096031
7、最终优化方案:因为Math.random() * 10000的重复性几率还不是很小,所以改用时间(毫秒做为种子),减少重复的机率,并且在上传方法里不需要判断了,多次一举(循环赋值不需要加index)
arr.map((item, index) => {
// 又因为是动态数据,id也是动态添加,所以加上随机数,这样使的id不会重复(三id,如果你杠,你就是对的)
this.copySave.push({url: item, id: Math.floor(Math.random() * new Date().getTime())});
})
async uploadSave(data) {
const formData = new FormData()
formData.append('file', data.file)
this.loadingSave = true
let res = await this.$http(this.$url.ORDER_PHOTO_UPLOAD, 'str', formData)
this.loadingSave = false
if (res.data.code == 0 || res.data.code == 200) {
let imgUrl = res.data.data.fileUrl
this.$message.success('上传成功');
this.copySave.push({url: imgUrl, id: Math.floor(Math.random() * new Date().getTime())})
this.copySave = this.copySave.slice(-3)
}
},
别在幸福中找烦恼