请小心使用 ng-repeat 中的 $index
自己自学的时候,遇到$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 之外依然有效,则必须在控制器中也进行过滤,这就需要一些不是很必要的重复代码。 值得庆幸的是本文中介绍的模式可以用来避免这种情况。
原文链接: 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的更多相关文章
- 走进AngularJs(二) ng模板中常用指令的使用方式
通过使用模板,我们可以把model和controller中的数据组装起来呈现给浏览器,还可以通过数据绑定,实时更新视图,让我们的页面变成动态的.ng的模板真是让我爱不释手.学习ng道路还很漫长,从模板 ...
- [中级] 有效删除URL中的index.php
如果你刚接触CI不久又或者刚刚研读CI的使用手册的话,关于如何有效删除URL中index.php以使URL看起来更友好美观的问题,可能是你面对的第一个较为复杂的问题!本贴不是原创,而是一个各种意见的综 ...
- 使用jQuery+huandlebars循环中索引(@index)使用技巧(访问父级索引)
兼容ie8(很实用,复制过来,仅供技术参考,更详细内容请看源地址:http://www.cnblogs.com/iyangyuan/archive/2013/12/12/3471227.html) & ...
- MySQL explain结果Extra中"Using Index"与"Using where; Using index"区别探究
问题背景 最近用explain命令分析查询sql执行计划,时而能看到Extra中显示为"Using index"或者"Using where; Using Index&q ...
- ThinkPHP 隐藏URL中的 index.php
去掉 URL 中的 index.php 通常的URL里面含有index.php,为了达到更好的SEO效果可能需要去掉URL里面的index.php ,通过URL重写的方式可以达到这种效果,通常需要服务 ...
- Handlebars.js循环中索引(@index)使用技巧(访问父级索引)
使用Handlebars.js过程中,难免会使用循环,比如构造数据表格.而使用循环,又经常会用到索引,也就是获取当前循环到第几次了,一般会以这个为序号显示在页面上. Handlebars.js中获取循 ...
- Elasticsearch——禁止Body中的index覆盖Url中的index参数
本篇继续一下Elasticsearch日常使用的技巧翻译. 在Elasticsearch有很多的api支持在body中指定_index等信息,比如mget或者msearch以及bulk. 默认的情况下 ...
- 用WIN7系统IIS的提示:数据库连接出错,请检查Conn.asp文件中的数据库参数设置
我用科讯的从4.0开始,去年开始很少用科讯做新站了,今天拿来做一下,结果悲剧了,数据库路径老是不对,百度一番又一番的,,最后终于给度娘解决了.分享出来给遇到同样的问题的人. 用WIN7系统IIS的注意 ...
- [tp3.2.1]开启URL(重写模式),省略URL中的index.php
重写模式(省略url中的index.php) 在apache配置文件httpd.conf中,查找 1.mod_rewrite.so, 启动此模块 2.AllowOverride , 值= All 3. ...
- jquery中的index方法
问题描述:灵活使用jquery中的index方法 方法签名:index([selector|element]) 用法概述:P1.index(P2) //调用者P1可以为对象或集合 参数为空,返回P1 ...
随机推荐
- sudo 无效命令
mac系统中由于不小心修改了/etc/sudoers下的权限为777,故而sudo命令不能使用. 解决办法 1.重新启动mac并且按command+s进入单用户界面 2.此时默认的系统状态是只读状态, ...
- Spring Cloud Zuul网关 Filter、熔断、重试、高可用的使用方式。
时间过的很快,写springcloud(十):服务网关zuul初级篇还在半年前,现在已经是2018年了,我们继续探讨Zuul更高级的使用方式. 上篇文章主要介绍了Zuul网关使用模式,以及自动转发机制 ...
- mysql 查看索引使用情况
show status like 'Handler_read%'; Handler_read_key 代表着一个行被索引值读取的次数,值很低表明索引不经常用到,增加索引对性能改善不高. Handle ...
- diffMerge安装配置使用
概述: 在用git进行源代码版本维护的时候,常常会进行各代码版本之前区别的查看,例如在每次提交改动前进行git diff 可以看到源文件代码相对相应版本或是远程仓库的改动情况,如果有冲突还需要进行me ...
- python_5_模块
创:5_4_2017 修: 什么是模块? --标准库+第三方库+自定义,为实现某一方面的功能集合(变量,函数,类) 如何安装第三方库? --pip install 第三方库 如何导入和使用模块? -- ...
- ueditor表格边框没有颜色的解决
问题: 用ueditor画表格,会发现表格存在,但是表格边框没有颜色. 解决方法: 需要对js文件中的样式进行修改,这里我引用的编辑器样式文件是ueditor.all.min.js,所以先找到该文件, ...
- Linux安装JDK、MySQL和Tomcat
1 依赖的安装 因为JDK.Tomcat和MySQL的安装过程中需要从网上下载部分支持包才可以继续,所以需要提前安装好依赖. yum install glibc.1686 yum -y install ...
- Docker几个基本常识
标签(linux): docker 此文来自本人学习以及网络整理而来. 笔者Q:972581034 交流群:605799367.有任何疑问可与笔者或加群交流 对于用户来说,可能一开始在不了解的情况下会 ...
- TCP/IP详解 卷1 第二十一章 TCP的超时与重传
21.1 引言 可靠性的保证之一就是超时重传 前面两个超时重传的例子 1) ICMP端口不能到达时,TFTP客户使用UDP实现了一个简单的超时和重传机制,假定5s是一个适当是时间间隔,并每隔5s进行 ...
- WindowXp-Windows7-Windows运行命令(转)
Win7里面按 Win+R 呼出运行界面,一下是它的一些常用命令: 1.cleanmgr: 打开磁盘清理工具 2.compmgmt.msc: 计算机管理 3.conf: 启动系统配置实用程序 4.ch ...