如何从 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 索引。特别是如果您使用orderByfilter。我认为使用$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】:

这里是 filterUnderscore 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 数组中删除元素/节点的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Angular.js 中从 DOM 中添加/删除 createElement

在JAVA中如何从数组中删除一个元素

如何使用 Angular JS 从外部范围访问数组值

C语言如何从数组中删除一个指定元素?

js删除对象数组

PHP:如何从数组中删除特定元素?