如何从 angular.js 数组中删除元素/节点
Posted
技术标签:
【中文标题】如何从 angular.js 数组中删除元素/节点【英文标题】:How to remove elements/nodes from angular.js array 【发布时间】:2013-08-20 14:45:12 【问题描述】:我正在尝试从数组$scope.items
中删除元素,以便在视图ng-repeat="item in items"
中删除项目
这里只是为了演示目的,这里有一些代码:
for(i=0;i<$scope.items.length;i++)
if($scope.items[i].name == 'ted')
$scope.items.shift();
如果有名称 ted,我想从视图中删除第一个元素,对吗?它工作正常,但视图重新加载所有元素。因为所有的数组键都发生了变化。这在我正在创建的移动应用程序中造成了不必要的延迟..
谁有解决这个问题的办法?
【问题讨论】:
我已经成功使用 splice 修改了一个用于 ng-repeat 的数组,没有奇怪的副作用。 看起来items是array的array,或者不能调用items[i].shift(); 您好,感谢您的回复。抱歉,我的问题代码中有错别字,我刚刚更新了它。 那为什么要从数组中删除第一个元素而不是i位置的元素呢? 3行就能解决你的问题,只需在控制器中添加$filter 【参考方案1】:从数组中删除项目没有火箭科学。要从任何数组中删除项目,您需要使用splice
:$scope.items.splice(index, 1);
。 Here is an example:
HTML
<!DOCTYPE html>
<html data-ng-app="demo">
<head>
<script data-require="angular.js@1.1.5" data-semver="1.1.5" src="https://ajax.googleapis.com/ajax/libs/angularjs/1.1.5/angular.js"></script>
<link rel="stylesheet" href="style.css" />
<script src="script.js"></script>
</head>
<body>
<div data-ng-controller="DemoController">
<ul>
<li data-ng-repeat="item in items">
item
<button data-ng-click="removeItem($index)">Remove</button>
</li>
</ul>
<input data-ng-model="newItem"><button data-ng-click="addItem(newItem)">Add</button>
</div>
</body>
</html>
JavaScript
"use strict";
var demo = angular.module("demo", []);
function DemoController($scope)
$scope.items = [
"potatoes",
"tomatoes",
"flour",
"sugar",
"salt"
];
$scope.addItem = function(item)
$scope.items.push(item);
$scope.newItem = null;
$scope.removeItem = function(index)
$scope.items.splice(index, 1);
【讨论】:
(index, 1)中的“1”是什么意思 @ShibinRagh,阅读文档:developer.mozilla.org/en/docs/Web/javascript/Reference/… 请注意$index
不一定匹配$scope.items
索引。特别是如果您使用orderBy
或filter
。我认为使用$index
是不可扩展的,可能很危险。
@AntoinePinsard 你有什么推荐的?
@stackPusher,如果我没记错的话,我使用了 bpaul 的解决方案 ***.com/a/22160628/1529346【参考方案2】:
对于任何返回此问题的人。从数组中删除项目的正确“角度方式”是使用 $filter。只需将 $filter 注入您的控制器并执行以下操作:
$scope.items = $filter('filter')($scope.items, name: '!ted')
您不需要加载任何额外的库或诉诸 Javascript 原语。
【讨论】:
如果您有一个名为“ted”和“teddy”的元素,并且只想删除“ted”元素,这是否可行? @Jervelund 是的,您可以在最后使用 true :$filter('filter')($scope.items, name: '!ted', true)
,请参阅docs.angularjs.org/api/ng/filter/filter
我认为这个答案应该是被接受的,因为它有角度。
是否可以使用过滤器删除包含特定数字 id 的元素? $filter('filter')($scope.items, id: 42, true);
用于查找元素,但我还没有找到否定它的方法,id: "!42"
不起作用,因为它是一个字符串。
这工作:$filter('filter')($scope.items, function(value, index) return value.id !== 42;);
【参考方案3】:
您可以使用纯 javascript - Array.prototype.filter()
$scope.items = $scope.items.filter(function(item)
return item.name !== 'ted';
);
【讨论】:
【参考方案4】:因为当你对数组执行shift()
时,它会改变数组的长度。所以for循环会被搞砸。您可以从头到尾循环来避免这个问题。
顺便说一句,我假设您尝试删除 i 位置的元素,而不是数组的第一个元素。 (代码中的$scope.items.shift();
将删除数组的第一个元素)
for(var i = $scope.items.length - 1; i >= 0; i--)
if($scope.items[i].name == 'ted')
$scope.items.splice(i,1);
【讨论】:
【参考方案5】:这里是 filter
和 Underscore library 可能会对您有所帮助,我们删除名称为“ted”的项目
$scope.items = _.filter($scope.items, function(item)
return !(item.name == 'ted');
);
【讨论】:
这是“角度”的方式!当然可以改进:$scope.items = $filter('filter').filter($scope.items, name: '!ted')
@bpaul 的改进不错,但看起来有错误,应该是:$scope.items = $filter('filter')($scope.items, name: '!ted')
@Eugene 一点也不。我使用了下划线库,添加了链接。
谢谢@Eugene,这是一个错字。我应该在发布之前测试代码!此外,这应该是一个答案,因为它不需要下划线(或任何其他库)并且是惯用的角度。我会添加它。【参考方案6】:
只是稍微扩展了“角度”解决方案。我想根据它的数字 id 排除一个项目,所以 !方法不起作用。 适用于 name: 'ted' 或 id: 42 的更通用的解决方案是:
mycollection = $filter('filter')(myCollection, id: theId , function (obj, test)
return obj !== test; );
【讨论】:
【参考方案7】:我喜欢@madhead 提供的解决方案
但是我遇到的问题是它不适用于排序列表,因此我没有将索引传递给删除函数,而是传递了项目,然后通过 indexof 获取索引
例如:
var index = $scope.items.indexOf(item);
$scope.items.splice(index, 1);
以下是 madheads 示例的更新版本: link to example
HTML
<!DOCTYPE html>
<html data-ng-app="demo">
<head>
<script data-require="angular.js@1.1.5" data-semver="1.1.5" src="https://ajax.googleapis.com/ajax/libs/angularjs/1.1.5/angular.js"></script>
<link rel="stylesheet" href="style.css" />
<script src="script.js"></script>
</head>
<body>
<div data-ng-controller="DemoController">
<ul>
<li data-ng-repeat="item in items|orderBy:'toString()'">
item
<button data-ng-click="removeItem(item)">Remove</button>
</li>
</ul>
<input data-ng-model="newItem"><button data-ng-click="addItem(newItem)">Add</button>
</div>
</body>
</html>
JavaScript
"use strict";
var demo = angular.module("demo", []);
function DemoController($scope)
$scope.items = [
"potatoes",
"tomatoes",
"flour",
"sugar",
"salt"
];
$scope.addItem = function(item)
$scope.items.push(item);
$scope.newItem = null;
$scope.removeItem = function(item)
var index = $scope.items.indexOf(item);
$scope.items.splice(index, 1);
【讨论】:
【参考方案8】:我对此的解决方案(没有导致任何性能问题):
-
使用 remove 方法扩展数组对象(我相信您不止一次需要它):
Array.prototype.remove = function(from, to) var rest = this.slice((to || from) + 1 || this.length); this.length = from < 0 ? this.length + from : from; return this.push.apply(this, rest); ;
我在我的所有项目中都使用它,感谢 John Resig John Resig's Site
-
使用 forEach 和基本检查:
$scope.items.forEach(function(element, index, array) if(element.name === 'ted') $scope.items.remove(index); );
最后,$digest 将在 angularjs 中触发,我的 UI 会立即更新,没有任何可识别的延迟。
【讨论】:
在遍历列表时删除元素真的安全吗? 一般来说,你应该小心这样做。我会说使用 .forEach 而不是 for 循环使其安全,因为 MDN developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/… 说:“forEach() 对数组中存在的每个元素按升序执行一次提供的回调。它不会为具有被删除或未初始化(即在稀疏数组上)。”因此,访问后/访问前删除的项目只是“忽略”,恕我直言,这对于这种情况是安全的。【参考方案9】:如果你有任何关联到列表的函数,当你创建拼接函数时,关联也会被删除。我的解决方案:
$scope.remove = function()
var oldList = $scope.items;
$scope.items = [];
angular.forEach(oldList, function(x)
if (! x.done) $scope.items.push( [ DATA OF EACH ITEM USING oldList(x) ] );
);
;
列表参数名为items。 参数 x.done 指示该项目是否将被删除。希望能帮到你。问候。
【讨论】:
【参考方案10】:使用 indexOf 函数并没有削减我的 REST 资源集合。
我必须创建一个函数来检索位于资源集合中的资源的数组索引:
factory.getResourceIndex = function(resources, resource)
var index = -1;
for (var i = 0; i < resources.length; i++)
if (resources[i].id == resource.id)
index = i;
return index;
$scope.unassignedTeams.splice(CommonService.getResourceIndex($scope.unassignedTeams, data), 1);
【讨论】:
【参考方案11】:我的解决方案非常简单
app.controller('TaskController', function($scope)
$scope.items = tasks;
$scope.addTask = function(task)
task.created = Date.now();
$scope.items.push(task);
console.log($scope.items);
;
$scope.removeItem = function(item)
// item is the index value which is obtained using $index in ng-repeat
$scope.items.splice(item, 1);
);
【讨论】:
【参考方案12】:我的物品有唯一的 ID。我通过使用 angulars $filter
服务过滤模型来删除一个:
var myModel = [id:12345, ...,,,...,];
...
// working within the item
function doSthWithItem(item)
...
myModel = $filter('filter')(myModel, function(value, index)
return value.id !== item.id;
);
您也可以使用模型项的 $$hashKey 属性:$$hashKey:"object:91"
【讨论】:
以上是关于如何从 angular.js 数组中删除元素/节点的主要内容,如果未能解决你的问题,请参考以下文章