循环使用el-upload上传图片引出对象拷贝的问题

项目场景:

最近毕设用Vue做一个电子商城,在做商品评价的时候,我想要对某一个订单的多个商品在同一页面分别进行评价(有点类似于美团优选的商品评价),但是图片上传出现了一点问题,随手记录一下。


问题描述

通过element的upload上传图片,我想要在el-upload的成功回调传参,将上传成功的图片地址添加到图片数组里面,结果循环数组每一项的图片数组都添加上传成功的图片地址

HTML代码:

<div v-for="(item, i) in goods" :key="i">
	<el-upload 
		:action="uploadUrl" 
		:headers="getAuthHeaders()" 
		list-type="picture-card" 
		:on-remove="handleRemove(item, res)" 
		:on-success="handleAvatarSuccess(item, res)"
	>
    	<i class="el-icon-camera"></i>
	</el-upload>
</div>

js代码

data() {
	return {
		goods:[],
		model:{
			score:null,
			content:'',
			contentImg:[],
		}
	}
},
methods:{
	handleRemove(item, res) {
      this.goods.forEach((v) => {
        if (v.goodsId == item.goodsId) {
          v.contentImg.forEach((n, i) => {
            if (n == res.response.url) {
              v.contentImg.splice(i, 1);
            }
          });
        }
      });
    },
	handleAvatarSuccess(item, res) {
	//想通过每一项的商品Id来识别每一项的储存位置,从而添加图片
		this.goods.forEach(v => {
			if(v.goodsId == item.goodsId){
				v.contentImg.push(res.url);
			}
		})
	},
	fetch() {
		const res = await this.$http.get('获取订单的接口')this.goods = (res.data?.goods || []).map(v= > {
		//想在这里给数组的每一项都添加 this.model 里面的属性
			return {...v, ...this.model} 
		})
	}
}

原因分析与解决方案:

主要有三个问题:

问题一:

使用el-upload想要传参的方式错误,直接传参会覆盖掉on-success原来的参数,on-success无法自定义传参。

解决:
通过查资料:

1)可以通过 :on-success=“res => handleAvatarSuccess(item,res)” 的方式来进行传参。

2)可以通过:on-success=“handleAvatarSuccess.bind(null, {‘index’:i, ‘data’:item})” 的方式创建函数的副本调用,通常用在解决循环中使用el-upload的问题

bind的语法:

 fun.bind(thisArg[, arg1[, arg2[, ...]]]) thisArg
  • 当绑定函数被调用时,该参数会作为原函数运行时的 this 指向。当使用 new 操作符调用绑定函数时,该参数无效。
  • arg1, arg2, … (可选)当绑定函数被调用时,这些参数加上绑定函数本身的参数会按照顺序作为原函数运行时的参数。

问题二:

由于我想让通过请求获取的数组 goods 每一项都添加有 data 中 model 对象中的属性,而使用 { …v, …this.model } 拷贝给 goods 数组每一项的属性都是共享同一块内存的,这是属于浅拷贝,只拷贝了对象的指针,而不是对象本身,新旧对象还是共享同一块内存。需要通过深拷贝创造一个一模一样的对象,新对象和原来的对象不共享同一块内存,修改新对象的时候不会改到原来的对象。

解决:

通过 JSON.parse(JSON.stringify( this.model )) 对 model 进行深拷贝


最后上解决后的代码:

HTML代码:

<div v-for="(item, i) in goods" :key="i">
	<el-upload 
		:action="uploadUrl" 
		:headers="getAuthHeaders()" 
		list-type="picture-card" 
		:on-remove="handleRemove.bind(null, {'index': i})" 
		:on-success="handleAvatarSuccess.bind(null, {'index': i})"
	>
    	<i class="el-icon-camera"></i>
	</el-upload>
</div>

js代码

data() {
	return {
		goods:[],
		model:{
			score:null,
			content:'',
			contentImg:[],
		}
	}
},
methods:{
	handleRemove(obj, res) {
    	this.goods[obj.index].contentImg.forEach((v, i) => {
        	if (v == res.response.url) {
            	this.goods[obj.index].contentImg.splice(i,1);
        	}
    	})
    },
	handleAvatarSuccess(obj, res) {
		this.goods[obj.index].contentImg.push(res.url);
	},
	fetch() {
		const res = await this.$http.get('获取订单的接口');
		this.goods = (res.data?.goods || []).map(v= > {
			let model = JSON.parse(JSON.stringify(this.model))
			return {...v, ...model} 
		})
	}
}

上图:
在这里插入图片描述

参考文章:
ELEMENTUI中EL-UPLOAD上传图片组件上传成功函数传自定义参数
vue element-ui v-for循环el-upload上传图片 动态添加、删除
理解 javascript 里的 bind() 函数

关于深拷贝,解决过程有试过用Object.assign(),但是不成功,原因详情看:vue 项目开发中的对象拷贝

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值