Vue问题:向含数组的对象添加元素时所有数组均被更新
问题:调用addBatch时所有item的batches数组都被同步更新
我声明了如下的items对象:
const newItem = {itemId: '', price: '0.00', discount: 0, discountedPrice: 0, batches: [2]} const items = ref([{...newItem, ...{id: 0}}])
我希望能向batches键中添加新成员,写了以下方法:
const addItem = () => { items.value.push({...newItem, ...{id: items.value.length}}) } const addBatch = (batches) => { console.log(batches) batches.push(0) }
但当我在模板中调用addBatch时,所有item的batches都被更新了:
<tr v-for="(item, index) in items" :key="item.id" class="bg-slate-200"> <td class="p-1 text-center align-top"> <input :name="'itemId[' + index + ']'" type="text" placeholder="Item..." v-model="item.itemId" class="rounded border border-gray-500 text-gray-900 p-1 w-full text-xs min-w-[100px]" /> </td> <td class="p-1 text-center align-top"> <div class="grid grid-cols-2"> <div> <input v-for="(batch, batchIndex) in item.batches" :key="batchIndex + 'batch'" :name="'quantity[' + index + '][]'" :value="batch" type="number" placeholder="Quantity..." min=".001" max="1000000000" step=".001" class="rounded border border-gray-500 text-gray-900 p-1 text-xs w-full" /> </div> <div> <button @click="addBatch(item.batches)" type="button" class="text-xs bg-green-600 flex p-1 items-center rounded text-white ml-1" ></button> </div> </div> </td> </tr>
我尝试了各种方法,但始终无法理解为何所有batches都会被更新,而不是仅更新传入函数的那一个?
原因分析
问题出在对象浅拷贝上:你用{...newItem}展开对象时,对于batches这种数组类型的属性,只会拷贝它的内存引用,不会创建新的数组实例。这就导致所有通过addItem添加的item,它们的batches都指向同一个数组。所以你调用batches.push(0)时,所有item都会同步看到这个数组的变化。
解决方案
创建新item时,要对batches做独立拷贝,确保每个item的batches都是专属的数组。有两种修改方式:
方式一:封装创建新item的函数
每次创建都生成全新的数组:
const createNewItem = (id) => { return { itemId: '', price: '0.00', discount: 0, discountedPrice: 0, batches: [2], // 每次创建新数组 id: id } } const items = ref([createNewItem(0)]) const addItem = () => { items.value.push(createNewItem(items.value.length)) } const addBatch = (batches) => { batches.push(0) }
方式二:保留原newItem,拷贝时手动克隆batches
在展开对象时单独复制数组:
const newItem = {itemId: '', price: '0.00', discount: 0, discountedPrice: 0, batches: [2]} const items = ref([{...newItem, batches: [...newItem.batches], id: 0}]) const addItem = () => { items.value.push({ ...newItem, batches: [...newItem.batches], // 克隆数组,生成新引用 id: items.value.length }) }
这样每个item的batches都是独立的数组,调用addBatch时只会修改当前点击的item对应的数组,不会影响其他item。
内容的提问来源于stack exchange,提问作者user5318896
相关产品推荐
相关产品推荐

