自己自学的时候,遇到$index不知道它是如何使用的,所以上网搜了一下,发现了这个关于使用$index可能会出现的一个小BUG,和大家分享一下

PS:我是小白,欢迎指正,非常感谢!

以下是全文:

“有客户投诉,说在删除指定的某条记录时,结果删掉的却是另外一条记录!”

看起来是个很严重的BUG。 有一次我们在工作中碰到了这个问题。 要定位这个BUG非常麻烦, 因为客户也不清楚如何重现这个问题。

后来发现这个Bug是由于在 ng-repeat 中使用了 $index 引发的。下面一起来看看这个错误是如何引发的, 以及如何避免这种bug产生,然后说说我们从中得到的经验和教训。

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

GitHub版:https://github.com/cncounter/translation/blob/master/tiemao_2015/04_ng_repeat_%24index/ng_repeat_%24index.md

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

原文日期: 2014-11-10

翻译日期: 2015-01-23

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

请小心使用 ng-repeat 中的 $index的更多相关文章

  1. 走进AngularJs(二) ng模板中常用指令的使用方式

    通过使用模板,我们可以把model和controller中的数据组装起来呈现给浏览器,还可以通过数据绑定,实时更新视图,让我们的页面变成动态的.ng的模板真是让我爱不释手.学习ng道路还很漫长,从模板 ...

  2. [中级] 有效删除URL中的index.php

    如果你刚接触CI不久又或者刚刚研读CI的使用手册的话,关于如何有效删除URL中index.php以使URL看起来更友好美观的问题,可能是你面对的第一个较为复杂的问题!本贴不是原创,而是一个各种意见的综 ...

  3. 使用jQuery+huandlebars循环中索引(@index)使用技巧(访问父级索引)

    兼容ie8(很实用,复制过来,仅供技术参考,更详细内容请看源地址:http://www.cnblogs.com/iyangyuan/archive/2013/12/12/3471227.html) & ...

  4. MySQL explain结果Extra中"Using Index"与"Using where; Using index"区别探究

    问题背景 最近用explain命令分析查询sql执行计划,时而能看到Extra中显示为"Using index"或者"Using where; Using Index&q ...

  5. ThinkPHP 隐藏URL中的 index.php

    去掉 URL 中的 index.php 通常的URL里面含有index.php,为了达到更好的SEO效果可能需要去掉URL里面的index.php ,通过URL重写的方式可以达到这种效果,通常需要服务 ...

  6. Handlebars.js循环中索引(@index)使用技巧(访问父级索引)

    使用Handlebars.js过程中,难免会使用循环,比如构造数据表格.而使用循环,又经常会用到索引,也就是获取当前循环到第几次了,一般会以这个为序号显示在页面上. Handlebars.js中获取循 ...

  7. Elasticsearch——禁止Body中的index覆盖Url中的index参数

    本篇继续一下Elasticsearch日常使用的技巧翻译. 在Elasticsearch有很多的api支持在body中指定_index等信息,比如mget或者msearch以及bulk. 默认的情况下 ...

  8. 用WIN7系统IIS的提示:数据库连接出错,请检查Conn.asp文件中的数据库参数设置

    我用科讯的从4.0开始,去年开始很少用科讯做新站了,今天拿来做一下,结果悲剧了,数据库路径老是不对,百度一番又一番的,,最后终于给度娘解决了.分享出来给遇到同样的问题的人. 用WIN7系统IIS的注意 ...

  9. [tp3.2.1]开启URL(重写模式),省略URL中的index.php

    重写模式(省略url中的index.php) 在apache配置文件httpd.conf中,查找 1.mod_rewrite.so, 启动此模块 2.AllowOverride , 值= All 3. ...

  10. jquery中的index方法

    问题描述:灵活使用jquery中的index方法 方法签名:index([selector|element]) 用法概述:P1.index(P2)  //调用者P1可以为对象或集合 参数为空,返回P1 ...

随机推荐

  1. iOS学习之Map,定位,标记位置的使用

    iOS上使用地图比Android要方便,只需要新建一个MKMapView,addSubView即可.这次要实现的效果如下: 有标注(大头针),定位,地图. 1.添加地图 1.1 新一个Single V ...

  2. 【视频编解码·学习笔记】3. H.264视频编解码工程JM的下载与编解码

    一.下载JM工程: JM是H.264标准制定团队所认可的官方参考软件.网址如下 http://iphome.hhi.de/suehring/tml/ 从页面中可找到相应的工程源码,本次选择JM 8.6 ...

  3. VIM 自定义语法高亮配置

    VIM 没有自动支持语法高亮,自己动手搞一搞,网上查了一堆资料,终于配置成功, 记录一下,以便后期查看. 总共两步: step1 : 定义语法规则 1)需要创建一个定义语法规则的文件,这个 actio ...

  4. 流程控制语句if、else、elif、break、continue

    1.控制流程 # if 判断语句 a = 12 if a>0: print('a大于0') if a<5: print('a大于5') else: print('哈哈哈') 2.基本形式: ...

  5. 程序员之殇 —— One program, One king (血月)

    Are we living in the time of the end? (程序员的时代是否已经终结了?) 最近,我时常问自己这个问题. 刚读完了一个美国博士的论文,UDT (UDP-based D ...

  6. _2_head_中标签

    创:20_3_2017修:5_4_2017 什么是title标签? --title   页面名(双) -- 整个html的页面名字,相当于一本书的书名 <title>北门吹雪</ti ...

  7. JavaScript之点赞特效

    在很多网站中登录后可以对你说喜欢的文章.图片之类的进行点赞,这个功能效果的实现就是我今天要写的东西.代码不长,但觉得还是很有用的,为 js 给用户交互体验上更加友好.在实现过程中,主要的思路有: 点赞 ...

  8. Linux普通用户修改owner非本人文件为什么成功

    关键字:错误提示:E45 已设定选项’readonly’(请加!强制执行) Linux对文件和目录有很好的权限管理,但今天遇到一个比较诡异的事情,普通用户对文件权限不可写,但可以强制保存该文件,这样就 ...

  9. junit断言总结

    我们平时编写自己的测试类,如果没有断言,那么就没写测试的必要了. JUnit框架用一组assert方法封装了最常见的测试任务.这些assert方法可以极大地简化单元测试的编写. Assert类包含了一 ...

  10. Mac 管理员变为了普通用户怎么办?

    开机的时候一直按住 command+s 出现命令行终端的时候按照以下顺序输入命令: /sbin/mount -uw    回车rm var/db/.AppleSetupDone   回车 reboot ...