zoukankan      html  css  js  c++  java
  • AngularJs 脏值检查及其相关

    今天突然就想写写$digest和$apply,这些都是脏值检查的主体内容。

    先以普通js来做一个简单的监控例子吧:

      var div = ducoment.getElementById("myDiv");
          div.addEventListener("click",function(e){
            console.log(e);
        })

    在这里,我们给一个div绑定了个点击事件,并且给这个绑定事件一个回调函数。这里我们就是给了这个div一个监听,当监听到有点击事件发生在此div上,则执行该回调函数。

    Angular的$watch也是这样的效果。拿ngModel为例:
      in html:     <input ng-model="value" />
      in controller.js:     $scope.value = "Hello World";
    我们只要改变input里的值,在controller里对应的$scope.value也会随之发生相同的变化。这里就是给$watch列表添加了一个监控函数,从而做到这个效果的。
    $watch列表就是给所有绑定到同一$scope对象的UI元素添加一个监控函数到$watch列表里。
    $watch列表会触发$digest循环,并且在$digest循环中通过“脏值检查”机制进行解析。
    脏值检查
    什么是脏值检查?简单来说,就是Angular检查模型的值是否发生了变化,而程序还没对该变化进行同步的机制。Angular将会通过脏值检查遍历整个$watch列表,只要当中的某个值发生了变化,应用就会退回到$digest循环中,直到检测到这个值不再发生任何变化,然后再启用新值并且继续遍历$watch列表。整个$watch列表循环后,且其中值都不再变化了,那么整个应用程序的model也就趋于稳定了,这时候才在View渲染该有的数据。
    这里有个报错需要注意,也是挺多人会遇到且提出的问题,到底是什么错误呢,发上来秀秀,想必大家不会陌生~

      Error: [$rootScope:infdig] 10 $digest() iterations reached. Aborting!

    $digest循环运行10次,Angular就会抛出这个异常,同时停止$digest循环。而10这个次数可以在config里面注入$rootScopeProvider服务并且配置:

      $rootScopeProvider.digestTtl(15);

    这时候,错误就变成了:

      Error: [$rootScope:infdig] 15 $digest() iterations reached. Aborting!

    哈哈,小伙伴们肯定会说:你个小贱人,不就是换个数值重新报错么.... 好吧,那么你上去看看本兽说的出现这个错误的原因,不就可以根据问题来解决了么 -。-
    上面那个服务是用于配置当值不稳定的时候,$digest循环几次自动跳出循环的,部分场景可能会用得到。
    关于$watch函数以及相关的使用,可以移步本兽的另一篇文章,url请狂戳这里:$watch 
    $digest循环是脏值检查机制的主体,那么$digest怎么玩呢?
    自动进入$digest我们已经知道了,比如$scope的$watch列表中值发生变化,则触发$digest循环。
    那么手动召唤我们伟大的$digest循环呢?我们可以直接召唤$digest (#01),也可以集齐一只$apply来召唤$digest。
    $apply()函数在框架外部让表达式在Angular上下文内部执行。好吧,这个确实听起来比较绕...
    下面来一段$apply的使用代码吧:

      <div ng-app="Demo" ng-controller="testCtrl as ctrl">
          <my-dir count="ctrl.count"></my-dir>{{ctrl.count}}
      </div>
      (function(){
         angular.module('Demo', [])
         .directive("myDir",myDir)
         .controller('testCtrl',testCtrl);
         function myDir(){
           return{
             restrict:'AECM',
             template:'<input type="button" value="click me" />',
             scope:{count:"="},
              link: function(scope, element, attrs) {
               element.bind('click', function() {
                  scope.count++;
                  scope.$apply();
               });
             }
           }  
         };
         function testCtrl() {
             this.count = 0;
         }
      }());

    顺便也扯下,该在啥时使用$apply
    Angular提供的可用于视图中任意指令都可调用$apply(),比如:ng-click,ng-change等等。
    还有一些Angular内置的服务会调用$digest()。比如:$http服务(在XHR请求完成并触发更新返回的promise中会调用$apply())、使用$timeout()。
    在我们使用第三方框架时或在自己写的指令当中使用。比如:jQuery(Angular不建议在controller内操作DOM,DOM操作应该在Directive中使用,所以jQuery代码也请写在指令里吧),上面的代码(也是在指令中使用)。

    关于$apply vs $digest ,请移步另一篇Github译文:( 译、持续更新 ) JavaScript小技巧介绍  #01 - AngularJs: $digest vs $apply 

  • 相关阅读:
    伯克利推出世界最快的KVS数据库Anna:秒杀Redis和Cassandra
    不要什么都学-打造自己的差异化价值
    gitlab markdown支持页面内跳转
    技术人员怎样提升对业务的理解
    为什么HDFS的副本数通常选择3?
    MySQL++简单使用记录.md
    log4cpp安装使用
    log4cxx安装使用
    epoll使用总结
    工作方法-scrum+番茄工作法
  • 原文地址:https://www.cnblogs.com/ys-ys/p/5027422.html
Copyright © 2011-2022 走看看