AngularJS实践之使用ng-repeat中$index的注意点
发现问题
最近有客户投诉,说在删除指定的某条记录时,结果删掉的却是另外一条记录!看起来是个很严重的BUG。有一次我们在工作中碰到了这个问题。要定位这个BUG非常麻烦,因为客户也不清楚如何重现这个问题。
后来发现这个Bug是由于在ng-repeat中使用了$index引发的。
一个简单动作(action)的列表
先来看看一个完整有效的ng-repeat示例。
<ulng-controller="ListCtrl"> <ling-repeat="iteminitems"> {{item.name}} <buttonng-click="remove($index)">remove</button> </li> </ul>
对应的控制器(controller)如下:
app.controller('ListCtrl',['$scope',function($scope){ //itemscomefromsomewhere,fromwheredoesn'tmatterforthisexample $scope.items=getItems(); $scope.remove=function(index){ varitem=$scope.items[index]; removeItem(item); }; }]);
看起来没什么问题,对吗?这段代码也没有任何特别值得注意的。
添加一个过滤器(filter)
然后,让我们来做一个小小的修改:给列表添加一个过滤器。这是很常见的做法,如果列表很长的话,例如允许用户进行搜索。
为了方便起见,假设我们通过searchFilter来查询列表中的记录。
<ulng-controller="ListCtrl"> <ling-repeat="iteminitems|searchFilter"> {{item.name}} <buttonng-click="remove($index)">remove</button> </li> </ul>
控制器的代码保持不变。看起来仍然没有问题,是吧?
事实上,有一个bug藏在里面。如果我不说,你能找到吗?如果能找到,你就已经是Angular大牛了.
请尽量不要使用$index
BUG其实是在控制器里面:
$scope.remove=function(index){ varitem=$scope.items[index]; removeItem(item); };
这里使用了index参数,然后就遇到了BUG:过滤后的索引(indexs)不匹配原始列表的索引。
幸运的是,有一个很简单的方法来避免这种问题:不要使用$index,而改成实际的item对象。
<ulng-controller="ListCtrl"> <ling-repeat="iteminitems|searchFilter"> {{item.name}} <buttonng-click="remove(item)">remove</button> </li> </ul>
控制器如下所示:
$scope.remove=function(item){ removeItem(item); };
注意,这里将remove($index)改成remove(item),并修改了$scope.remove函数来直接操作传过来的对象。
这个小小的修改就完全避免了刚才的BUG。
为了更好地说明问题以及解决方案,请参考interactiveexample。
从中可以学到什么?
第一个教训当然是在使用$index要小心一点,因为以某些方式使用时很可能会产生BUG。
第二个教训是,请记住类似这样的模式,则可以用更好的做事方式,可以完全避免某些类型的BUG。我强烈建议大家现在不要使用$index,从这种简单的思维转变中,就可以减少代码中的很多BUG。
第三个教训是测试并不是什么时候都有用。即便有自动化测试,也覆盖了足够多的情形,但对于依赖特定输入的情况,也很容易错过某些BUG。错误本身并不是每次都会出现,即使你也用过滤来测试。
第四个教训是不要破坏抽象——这一点很容易被忽略。理论上$index是由ng-repeat创建的一个“模板变量(templatevariable)”。这只在repeat块里面有意义(并正确起作用)。当我们将它的值传递到外面时,它就失去了上下文从而不再有效。如果确实想让它在repeat之外依然有效,则必须在控制器中也进行过滤,这就需要一些不是很必要的重复代码。值得庆幸的是本文中介绍的模式可以用来避免这种情况。
结束语
以上就是关于AngularJS实践之ng-repeat中$index使用注意事项的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,如果有疑问大家可以留言交流。
原文链接:AngularJSbestpractices:Becarefulwhenusingng-repeat's$index
原文日期:2014-11-10
翻译日期:2015-01-23
翻译人员:铁锚http://blog.csdn.net/renfufei