watchCollection:监听集合元素的变化,而不能监听到集合元素内部的属性变化,只要集合中元素的引用没有发生变化,则认为无变化。用这个api也可以监听普通对象的第一层属性变化。

  watch:监听数据有没有发生变化,引用有无发生变化、原始类型数值有无发生变化等。除非指定第三个参数为true,否则不会对比对象的内层(多层)属性的变化,而仅仅对比引用。

  ngRepeat的检测 = watchCollection + watch(第三个参数为true)。

  默认情况下,ngRepeat使用列表元素对象的$$haskKey来标识关联对应的dom(angular会为不同引用的对象创建不同的$$hashKey),如果列表元素不是对象而是原始数据类型,则以元素的值来标识。在同一个列表中,标识必须唯一,否则报错,也可以通过track by xx 来自己指定标识的方式,如track by $index 就是用列表的索引来进行标识。

  ngRepeat会为每个单元创建一个作用域,然后把当前循环的状态($index,$first等)传递到这个作用域中,因为这个作用域是原型继承于外部作用域的,所以当ngRepeat出现嵌套的时候,可以通过ngInit把外层循环的index记录下来共内层循环使用:

<div ng-repeat="item in ones" ng-init="outerIndex=$index">
<span ng-repeat="item in twos" >the outer index is {{outerIndex }}</span> <br>
</div>

列表优化

  默认情况下,当列表中的元素引用发生变化(脏检测时发现的,使用的是watchCollection),angular仅仅会把对应变化的元素item的dom进行移除,然后重新生成一个新的dom替换进去,其余不需要变化。这就意味着当整个列表都发生变化时,整个dom列表会全部移除,生成新的全部替换进去。

  有没有办法改变了列表item的引用,却不生成新的dom进行替换呢?答案是可以的,但要指定track by。以下进行测试:

<body ng-app="app">
<div ng-repeat="item in ones">{{item}}</div>
<button ng-click="changeArr()">changeArr</button>
<button ng-click="getVal()">getVal</button>
</body>
<script>
var app = angular.module("app",[]);
app.run(function($rootScope){
$rootScope.ones = [{a:1},{a:2},{a:3}]; setTimeout(setVal,100); $rootScope.changeArr = function(){
$rootScope.ones[0] = {a:1,b:2};
}
$rootScope.getVal = function(){
console.log(document.querySelectorAll("div")[0].data)
console.log(document.querySelectorAll("div")[1].data)
}
});
function setVal(){
document.querySelectorAll("div")[0].data = 0;
document.querySelectorAll("div")[1].data = 1;
}
</script>

以上代码中,点击getVal,输出01,接着点击changeArr,更换了一个列表元素,界面上出现变化,接着点击getVal,输出undefined 1 。

结论:没有使用track by,当列表元素的引用被替换时,对应的dom也会被替换,之前绑定在上面的数据自然也就没了。

接下来使用track by 进行dom复用:

<div ng-repeat="item in ones track by item.a">{{item}}</div>

修改后,点击changeArr,界面发生变化,接着点击getVal,输出01 。

根据以上现象总结angular的列表渲染机制:

所以优化的策略就是,显式指定track by,能减少dom的创建,有利于dom的复用

最新文章

  1. 如何在多线程leader-follower模式下正确的使用boost::asio。
  2. 2016HUAS暑假集训训练2 K - Hero
  3. Linux内核同步机制之(二):Per-CPU变量
  4. Nginx return 关键字配置小技巧
  5. IP地址漂移的实现与原理
  6. AR模式
  7. const和readonly差别
  8. C#实现多国语言的界面切换
  9. 解决方案:安装wordpress出现500 Internal Server Error
  10. STL vector 用法介绍
  11. adoquery查询语句sql动态查询删除方法
  12. Flex性能调优相关的一些总结
  13. 支持向量机SVM(二)
  14. memcached 与 redis 的区别和具体应用场景
  15. Bzoj1899: [Zjoi2004]Lunch 午餐
  16. Django目录
  17. 【转】解决Android 6.0 NoSuchContextException 和WEBVIEW_undefined 的问题
  18. Centos搭建NFS服务及客户端访问
  19. Lambda根据属性名字选择或筛选
  20. jquery checkbox勾选/取消勾选只能操作一次的诡异问题

热门文章

  1. Codeforces Round #541 (Div. 2) C.Birthday
  2. Codeforces 1137B(kmp next数组构造)
  3. E. 打击判定 判断矩形是否相交
  4. 湖南省2016省赛题。1809: Parenthesis 线段树
  5. Dubbo理论知识
  6. 安卓新的联网方式 Volley的使用(2)
  7. Linux 环境下安装 Nginx+php+mysql 开发环境
  8. sql server 日期 查询技巧
  9. Xilinx FPGA结构
  10. IOS与android