使用Angular CDK Drag-Drop更新拖拽项属性时重复条目同步更新问题
问题描述
我有一个条目列表,需要将每个条目拖拽至可放置容器中,当前使用@angular/cdk/drag-drop的copyArrayItem方法实现复制拖拽,希望拖拽后能更新条目部分属性。但遇到问题:把‘Item-1’两次拖拽到容器后,更新其中一个条目的属性时,两个条目属性会同步变化。请问如何解决,或者怎么对拖拽到容器里的唯一条目单独更新属性?
问题根源
copyArrayItem默认执行浅拷贝,两次拖拽同一个源条目时,容器内的两个条目指向同一个内存引用。因此修改其中一个条目属性时,另一个会同步变化。
解决方案
放弃直接使用copyArrayItem,手动创建源条目的深拷贝后再添加到目标数组,确保每个拖拽生成的条目都是独立对象。
修改后的关键代码
1. 更新dropControl方法(替换浅拷贝为深拷贝)
dropControl(event: any): void { if (event.previousContainer !== event.container) { // 对源条目执行深拷贝,避免引用共享 const copiedControl = JSON.parse(JSON.stringify(event.previousContainer.data[event.previousIndex])); // 将深拷贝后的条目插入目标数组 event.container.data.splice(event.currentIndex, 0, copiedControl); this.openDetailsEditorDialog(event); } else { moveItemInArray(event.container.data, event.previousIndex, event.currentIndex); } if (event.previousContainer.data) { this.controls = this.controls.filter((control) => !control.droppedFlag); } }
2. 处理特殊类型的深拷贝(可选)
如果ControlType包含函数、Symbol、循环引用等JSON无法序列化的类型,改用structuredClone API实现深拷贝:
const copiedControl = structuredClone(event.previousContainer.data[event.previousIndex]);
3. 同步更新dropListExited方法(避免潜在的引用问题)
dropListExited(event: any): void { const currentIndex = event.container.data.findIndex( (control: ControlType) => control.type === event.item.data.type ); // 对条目执行深拷贝后再添加回源列表 const clonedItem = JSON.parse(JSON.stringify(event.item.data)); this.controls.splice(currentIndex + 1, 0, { ...clonedItem, droppedFlag: true, }); }
原理说明
深拷贝会完整复制对象的所有层级属性,生成一个全新的内存对象。这样容器内的每个条目都拥有独立的引用,修改其中一个时不会影响其他条目。
内容的提问来源于stack exchange,提问作者Akhil Joseph
相关产品推荐
相关产品推荐

