zoukankan      html  css  js  c++  java
  • angular 列表渲染机制

      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的复用

  • 相关阅读:
    【转载】JS中bind方法与函数柯里化
    计算机中位(bit), 字节(byte), 字(word)的关系
    MySQL 正则(Regular Expression) 邮箱(Email)
    eclipse remote system explorer operation
    Hibernate save, saveOrUpdate, persist, merge, update 区别
    产品经理 写SQL
    DevOps Scrum Agile Tech Debt
    SpringMVC 集成 jackson,日志格式报错:org.codehaus.jackson.map.JsonMappingException: Can not construct instance of java.util.Date from String value
    EDAS Serverless & Kubernetes SLB LVS Nginx
    阿里巴巴 开发者 工具 开源 社区
  • 原文地址:https://www.cnblogs.com/hellohello/p/8068008.html
Copyright © 2011-2022 走看看