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

 更新时间:2016年12月22日 17:20:23   作者:铁锚  
最近通过客户的投诉主要到在ng-repeat中使用了$index引发的一个bug,下面一起来看看这个错误是如何引发的, 以及如何避免这种bug产生,然后说说我们从中得到的经验和教训。有需要的朋友们可以参考借鉴,下面来一起看看吧。

发现问题

最近有客户投诉,说在删除指定的某条记录时,结果删掉的却是另外一条记录!看起来是个很严重的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。

      第二个教训是,请记住类似这样的模式,则可以用更好的做事方式,可以完全避免某些类型的BUG。 我强烈建议大家现在不要使用 $index, 从这种简单的思维转变中,就可以减少代码中的很多BUG。

      第三个教训是测试并不是什么时候都有用。 即便有自动化测试,也覆盖了足够多的情形, 但对于依赖特定输入的情况,也很容易错过某些BUG。 错误本身并不是每次都会出现,即使你也用过滤来测试。

      第四个教训是不要破坏抽象 —— 这一点很容易被忽略。理论上 $index 是由 ng-repeat 创建的一个 “模板变量(template variable)”。 这只在 repeat 块里面有意义(并正确起作用)。 当我们将它的值传递到外面时,它就失去了上下文从而不再有效。 如果确实想让它在 repeat 之外依然有效,则必须在控制器中也进行过滤,这就需要一些不是很必要的重复代码。 值得庆幸的是本文中介绍的模式可以用来避免这种情况。

结束语

以上就是关于AngularJS实践之ng-repeat中$index使用注意事项的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,如果有疑问大家可以留言交流。

原文链接: AngularJS best practices: Be careful when using ng-repeat's $index

原文日期: 2014-11-10

翻译日期: 2015-01-23

翻译人员: 铁锚 http://blog.csdn.net/renfufei

相关文章

  • AngularJS执行流程详解

    AngularJS执行流程详解

    本文主要介绍了AngularJS的执行流程。具有很好的参考价值,下面跟着小编一起来看下吧
    2017-02-02
  • angular中使用路由和$location切换视图

    angular中使用路由和$location切换视图

    这篇文章主要介绍了angular中使用路由和$location切换视图,需要的朋友可以参考下
    2015-01-01
  • 浅谈Angular的$q, defer, promise

    浅谈Angular的$q, defer, promise

    本文主要对Angular的 $q, defer, promise进行实例分析介绍。具有很好的参考价值,需要的朋友一起来看下吧
    2016-12-12
  • AngularJS动态绑定ng-options的ng-model实例代码

    AngularJS动态绑定ng-options的ng-model实例代码

    本篇文章主要介绍了AngularJS动态绑定ng-options的ng-model实例代码,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-06-06
  • Angular中使用ui router实现系统权限控制及开发遇到问题

    Angular中使用ui router实现系统权限控制及开发遇到问题

    这篇文章主要介绍了Angular中使用ui router实现系统权限控制及开发遇到问题的相关资料,本文分步骤介绍的非常详细,具有参考借鉴价值,需要的朋友可以参考下
    2016-09-09
  • AngularJs Injecting Services Into Controllers详解

    AngularJs Injecting Services Into Controllers详解

    本文主要介绍AngularJs Injecting Services Into Controllers的知识,这里整理了一下相关资料,及示例代码,帮助大家学习和理解,有兴趣的小伙伴可以参考下
    2016-09-09
  • 妙用Angularjs实现表格按指定列排序

    妙用Angularjs实现表格按指定列排序

    使用AngularJS的过滤器,可以很容易的实现在表格中,点击某一列标题进行排序,实现代码也很简单,下面小编给大家分享angularjs实现表格按指定列排序的实现代码,需要的的朋友参考下吧
    2017-06-06
  • Angularjs自定义指令Directive详解

    Angularjs自定义指令Directive详解

    Directive是一个非常棒的功能。可以实现我们自义的的功能方法。下面通过实例代码给大家介绍Angularjs自定义指令Directive相关知识,感兴趣的朋友一起学习吧
    2017-05-05
  • AngularJS身份验证的方法

    AngularJS身份验证的方法

    在客户端使用AngularJS做身份验证的话,推荐使用service来做,下面脚本之家小编给大家介绍AngularJS身份验证的方法,感兴趣的朋友一起学习吧
    2016-02-02
  • angular+webpack2实战例子

    angular+webpack2实战例子

    本篇文章主要介绍了angular+webpack2实战例子,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-05-05

最新评论