AngularJS中删除列表项时另一列表同项同步删除问题排查
嘿,这问题我太熟了——典型的JavaScript引用类型踩坑!咱们先把问题根源说清楚,再给你具体的修复方案。
问题原因
你服务里的locationList.list和currentlocation.editList都是引用类型(数组/对象),而JavaScript里引用类型的赋值是传递内存地址,不是复制内容。也就是说,当你调用setCurrentList把源列表直接赋值给currentlocation.editList时,这两个变量其实指向的是同一个数组。所以你删其中一个列表的项,另一个自然也跟着变——因为它们根本就是同一个东西!
看你服务里的这段代码,就是问题的核心:
setCurrentList:function(currentList){ currentlocation.editList = currentList; // 直接赋值引用,导致两个列表共享同一个内存地址 },
解决方案:给列表做拷贝,创建独立副本
要让两个列表互不影响,就得在赋值的时候复制一份新的数组/对象,而不是直接传递引用。AngularJS本身就提供了非常方便的深拷贝工具angular.copy(),当然也可以用其他拷贝方式,分两种情况:
情况1:列表项是基本类型(字符串、数字、布尔)
如果你的列表里都是基本类型,浅拷贝就够了,用扩展运算符或者slice()都可以:
setCurrentList:function(currentList){ // 用扩展运算符浅拷贝数组 currentlocation.editList = [...currentList]; // 或者用slice():currentlocation.editList = currentList.slice(); },
情况2:列表项是嵌套对象
如果列表里是嵌套的对象(比如每个项是{id: 1, name: "北京"}这种),浅拷贝只会复制对象的引用,还是会出现联动问题,这时候就得用深拷贝。推荐用AngularJS内置的angular.copy(),它能递归复制所有层级的内容:
setCurrentList:function(currentList){ // 深拷贝,创建完全独立的副本 currentlocation.editList = angular.copy(currentList); },
同样,为了避免其他地方出现类似问题,setAllLocationList也最好改成拷贝赋值:
setAllLocationList:function(allLocationList){ locationList.list = angular.copy(allLocationList); },
控制器里的使用示例
修改完服务后,控制器里正常调用就行,现在两个列表就是完全独立的了:
app.controller('LocationController', function(data) { // 获取源位置列表 const allLocations = data.getAllLocationList(); // 设置当前编辑列表(服务内部会做拷贝) data.setCurrentList(allLocations); // 现在删除当前列表的项,不会影响源列表 const currentEditList = data.getCurrentList(); currentEditList.splice(0, 1); // 只修改currentEditList,源列表allLocations完全不受影响 });
总结
核心就是一句话:不要直接引用同一个数组/对象,通过拷贝创建独立副本。这样两个列表的操作就彻底解耦了,删其中一个再也不会影响另一个啦!
内容的提问来源于stack exchange,提问作者Belhanda

