transition-group标签下循环报错:Emitted value instead of an instance of Error) Do not use v-for index as key

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)
  }
},

别在幸福中找烦恼

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值