11
$scope.clearCompleted = function()
        {
            angular.forEach($scope.todos, function(todo, i)
            {
                if(todo.done)
                {
                    $scope.todos.splice(i, 1);
                }
            });

            if($scope.todos.length == 0)
            {
                $scope.isEmpty = true;
            }
        }

这是我从数组中删除“完成”待办事项的代码,但是当一个接一个地删除两个待办事项时,它只会删除第二个。我认为这是因为拼接函数重置并返回拼接数组。

4

5 回答 5

19

您从迭代的数组中拼接元素,因此“todos”中的索引减少了。对不起,我的英语不好。

var notDonedTodos = [];
angular.forEach($scope.todos, function(todo, i)
{
    if(!todo.done)
    {
       notDonedTodos.push(todo);
    }
});

$scope.todos = notDonedTodos;
于 2013-06-02T16:03:58.213 回答
19

发生这种情况是因为forEach只知道数组的初始状态,因此调用您的方法两次,即使第一次调用从数组中删除了一个项目。只需执行一个简单的 while 循环即可:

var i = $scope.todos.length;
while (i--){
    if ($scope.todos[i].done){
        $scope.todos.splice(i, 1);
    }
}
于 2013-06-02T16:04:55.090 回答
7

我发现自己的替代方法是使用 array.filter 方法。这是基于对象键过滤数组的最简单方法。如果你正在处理一个 IE8 项目(可怜的你),你需要为这个函数添加一个 polyfill,因为它对 JavaScript 来说是相当新的。

你需要知道的关于 javascript 的一切

答案代码:

$scope.clearCompleted = function() {
    $scope.todos = $scope.todos.filter(function(item) {
        return !item.done;
    });
}
于 2015-01-13T09:49:22.850 回答
3

迭代的问题each是它从数组中删除了一个项目,导致迭代被跳过。jQuery 有一个很好的grep方法,它返回所有符合特定条件的元素,该条件由提供的匿名函数确定。

var todos =[{id:1, done:false},{id:2, done:true},{id:3, done:true}];

function removeCompleted(todos){
    return $.grep(todos,function(todo){
        return todo.done == false;
    });
}

todos = removeCompleted(todos);
console.log(todos);

工作示例 http://jsfiddle.net/ktCEN/

文档

于 2013-06-02T16:21:05.620 回答
2

作为另一种选择,您可以在每次执行splice. 例如:

$scope.clearCompleted = function() {
    angular.forEach($scope.todos, function(todo, i) {
        if(todo.done) {
            $scope.todos.splice(i, 1);
            i--;
        };
    });

    if($scope.todos.length == 0) {
        $scope.isEmpty = true;
    };
}

每次修改数组时,这都会调整索引以保持其有效性。您仍然可以使用angular.forEach,并且您最终不会得到数组的两个副本。

于 2015-01-12T17:02:55.010 回答