• ng-repeat 中的 track by $index


     

    用ng-repeat指令遍历一个javascript数组,当数组中有重复元素的时候,angularjs会报错,这是因为ng-Repeat不允许collection中存在两个相同Id的对象。

    对于数字或者字符串等基本数据类型来说,它的id就是它自身的值。因此数组中是不允许存在两个相同的数字的。为了规避这个错误,需要定义自己的track by表达式。

    // 业务上自己生成唯一的id
    item in items track by item.id

    //或者直接拿循环的索引变量$index来用
    item in items track by $index

    Error: [ngRepeat:dupes]这个出错提示具体到题主的情况,意思是指数组中有2个以上的相同数字。ngRepeat不允许collection中存在两个相同Id的对象

    一个简单动作(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 之外依然有效,则必须在控制器中也进行过滤,这就需要一些不是很必要的重复代码。 值得庆幸的是本文中介绍的模式可以用来避免这种情况。

  • 相关阅读:
    recovery&linux系统升级数据更新分析总结
    recovery 强制执行恢复出厂设置(Rescue Party)
    recovery 恢复出厂设置失败Data wipe failed
    system.img镜像转换为system.new.dat + system.transfer.list
    system.transfer.list版本进化
    项目微管理2
    项目微管理1
    项目微管理0
    项目微管理
    《软件小设计》推出
  • 原文地址:https://www.cnblogs.com/xiongzuyan/p/5984626.html
Copyright © 2020-2023  润新知