首页 > 语言 > JavaScript > 正文

AngularJS实践之使用ng-repeat中$index的注意点

2024-05-06 15:04:22
字体:
来源:转载
供稿:网友

发现问题

最近有客户投诉,说在删除指定的某条记录时,结果删掉的却是另外一条记录!看起来是个很严重的BUG。 有一次我们在工作中碰到了这个问题。 要定位这个BUG非常麻烦, 因为客户也不清楚如何重现这个问题。

后来发现这个Bug是由于在 ng-repeat 中使用了 $index 引发的。

一个简单动作(action)的列表

先来看看一个完整有效的ng-repeat示例。

<ul ng-controller="ListCtrl"> <li ng-repeat="item in items"> {{item.name}} <button ng-click="remove($index)">remove</button> </li></ul>

对应的控制器(controller)如下:

app.controller('ListCtrl', ['$scope', function($scope) { //items come from somewhere, from where doesn't matter for this example $scope.items = getItems(); $scope.remove = function(index) { var item = $scope.items[index]; removeItem(item); };}]);

看起来没什么问题,对吗? 这段代码也没有任何特别值得注意的。

添加一个过滤器(filter)

然后,让我们来做一个小小的修改: 给列表添加一个过滤器。 这是很常见的做法,如果列表很长的话,例如允许用户进行搜索。

为了方便起见, 假设我们通过 searchFilter 来查询列表中的记录。

<ul ng-controller="ListCtrl"> <li ng-repeat="item in items | searchFilter"> {{item.name}} <button ng-click="remove($index)">remove</button> </li></ul>

控制器的代码保持不变。 看起来仍然没有问题,是吧?

事实上,有一个bug藏在里面。 如果我不说, 你能找到吗? 如果能找到,你就已经是Angular大牛了.

请尽量不要使用 $index

BUG其实是在控制器里面:

$scope.remove = function(index) { var item = $scope.items[index]; removeItem(item);};

这里使用了 index参数, 然后就遇到了BUG: 过滤后的索引(indexs)不匹配原始列表的索引。

幸运的是,有一个很简单的方法来避免这种问题: 不要使用$index,而改成实际的item对象。

<ul ng-controller="ListCtrl"> <li ng-repeat="item in items | searchFilter"> {{item.name}} <button ng-click="remove(item)">remove</button> </li></ul>

控制器如下所示:

$scope.remove = function(item) { removeItem(item);};

注意, 这里将 remove($index) 改成 remove(item) , 并修改了 $scope.remove 函数来直接操作传过来的对象。

这个小小的修改就完全避免了刚才的BUG。

为了更好地说明问题以及解决方案,请参考 interactive example 。

从中可以学到什么?

      第一个教训当然是在使用 $index 要小心一点,因为以某些方式使用时很可能会产生BUG。

发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表

图片精选