angularjs框架$apply,$digest和$watch实例讲解

angularjs框架$apply,$digest和$watch理解

                                                                                    ——我一直不太信任自己的记忆力,所以我把它们都写下来

 

一、$aplly()添加普通js代码到angular框架

代码演示前先看看$apply方法的作用:$apply方法可以在angularjs框架之外执行angularJs表达式。现在不明白没关系,先看代码

<p ng-controller="myCtrl">{{message}}</p>
<script type="text/javascript">
        function myCtrl($scope) {
          $scope.message ="等待3秒";    
          setTimeout(function () {
             console.log('message已刷新');
            $scope.message ="等了3秒";
          }, 3000); 
        }
</script>

   运行上面的代码,显示“等待3秒”。但是过了3秒之后 message的内容并没有变成“等了3秒”。控制台却打印出“message已刷新”,所以 $scope.message ="等了3秒"; 这句代码已经执行了。 很显然数据的更新并没有被angular觉察到。看看另一段代码

<p ng-controller="myCtrl">{{message}}</p>

<script type="text/javascript">
        function myCtrl($scope) {
          $scope.message ="等待3秒";    
          setTimeout(function () {
             console.log('message已刷新');
             $scope.$apply(function () {
              $scope.message ="等了3秒";
             });
          }, 3000); 
        }
</script>

  代码可以看得出我们把刷新数据的内容加到$apply方法内部了。这次运行代码3秒过后message的值变成了 “等了3秒”。

    回到开头我们再看看$apply方法的作用:$apply方法可以在angularjs框架之外执行angularJs表达式。很明显,我们更新message的值在myCtrl函数中,而不是在angular作用域下面。$apply在与其他js代码集成时很有用。

 

二、$digest 循环检测

     在第一段代码$scope.message ="等了3秒"; 后面增加一行代码$scope.$degist()或者$scope.$apply();也能实现我们的目的。$digetst循环检测view绑定的数据是否变化,如果变化了则更新它。其实调用$apply方法接下来也是$digest检测绑定数据的变化,然后更新view。是不是一头雾水?这是angularjs初学者的第一个关隘,很多初学者对angularjs的数据绑定是如何工作的相当疑惑。一开始我也没有深究,为了便于记忆,理解成onkeydown事件的处理。

 

三、$watch队列

    按道理来讲应该先讲$watch,然后是$digest,接着$apply。可笔者是从初学者的实用角度出发,毕竟$apply更贴近于实际应用。

     在angular框架,每次绑定数据到view时都会向$watch队列里添加一个$watch,对数据变化的检测就是$watch。看个代码

用户:<input type="text" ng-model="name"/>密码:<input type="password" ng-model="pass"/>

在这里我们有个$scope.name,他被绑定在了第一个输入框上,还有个$scope.pass,它被绑定在了第二个输入框上,然后我们在$watch 队列里面加入两个$watch

再看一段代码

app.controller('MainCtrl',function($scope){
  $scope.foo ="Foo";
  $scope.world ="World";});

hello{{World}}

      这里虽然我们在Controller中给$scope添加了两个东西,但是view层我们只绑定了一个{{World}}  ,所以只生成了一个$watch。      

看一个比较复杂的例子,以便更好理解$watch      

app.controller('MainCtrl',function($scope){
  $scope.people =[...];//假设有10个元素});

index.html

<ul><ling-repeat="person in people">
      {{person.name}} - {{person.age}}
  </li></ul>

    这里又生成了多少个$watch呢?每个person有两个(一个name,一个age),然后ng-repeat又有一个,循环了十次,因此10个person一共是(2 * 10) +1,也就是说有21个$watch。 因此,每一个绑定到了UI上的数据都会生成一个$watch。对,那这些$watch是什么时候生成的呢? 当我们的模版加载完毕时,也就是在linking阶段(Angular分为compile阶段和linking阶段---译者注),Angular解释器会寻找每个directive,然后生成每个需要的$watch。听起来不错哈,但是,然后呢?

    接下来当然是$degist循环遍历$watch队列,检查是否有数据发生变化,当$degist循环完毕,如果有改变则更新view。

 英语好的看看这篇文章,保证受益匪浅。

http://angular-tips.com/blog/2013/08/watch-how-the-apply-runs-a-digest/

 

猜你喜欢

转载自zyqwst.iteye.com/blog/2294896