AngularJS digest循环

来源:互联网 发布:网络机柜安装规范 编辑:程序博客网 时间:2024/05/29 15:09

本篇文章参考了AngularJS权威教程。
本篇文章参考了http://blog.csdn.net/dm_vincent/article/details/38705099

1.简介

  AngularJS只用几行代码就实现了数据绑定,并能实时进行视图的更新,这里面digest循环功不可没。digest循环会进行检查scope模型的数据是否发生变化从而执行相应的动作,其中最重要的两个组成部分是$watch列表(或称为watcher列表)和$evalAsync列表。
  

2.$watch 列表

  当你写下某个表达式{{ text }}时,AngularJS会在幕后为你在scope模型上设置一个watcher,当数据发生变化时,watcher会负责更新View。这个watcher和我们平时使用的$watch一样。对于所有绑定给同一$scope对象的UI元素,只会添加一个$watch,因为只要一个$watch就足够监控一个对象,把操作合在一起就可以了。

3. $apply

  当你进行了可能更新Scope的操作(比如点击按钮触发事件),diggest循环就会被AngularJS自动调用。实际上,AngularJS并不会直接调用$scope.$digest(),而是会先调用$scope.$apply(),后者会调用$rootScope.$digest()。也就说,一轮循环首先从rootScope开始,随后到其所有的子scope。
  $apply方法可以接收一个可选的参数,该参数是字符串或函数。如果是字符串,那么$apply()会在这个字符串上调用eval()。$exceptionHandler会捕获和处理函数或eval()执行时发生的异常。不管有没有参数,$apply最后都会调用$rootScope.$digest()。
  什么时候才需要我们自己手动使用apply呢?AngularJS只负责其内部上下文环境发生变化时自动做出更新,也就是说,如果你在AngularJS上下文以外的地方修改了$scope(这种情况常发生在用第三方的插件,或是用setTimeout()的时候),那么你就得手动调用$apply通知AngularJS做出更新。
  下面是一个简单的例子,点击第一个按钮一秒钟后没反应,点击第二个按钮时第一个按钮改变的值刷新,因为此时会调用$apply(),然后1秒后再刷新成其他值。这里不推荐写完代码后再调用$apply()无参方法,而是推荐把要做的操作放到函数里传进$apply(),因为后者能够处理异常。

<body ng-app="myApp" ng-controller="myController">    <p> {{ text }}</p>    <input type="button" value="没用apply" ng-click="changeWithoutApply()"/>    <input type="button" value="使用apply" ng-click="changeWithApply()"/>    <script>        var app = angular.module("myApp",['ionic']);        app.controller("myController", function ($scope) {            $scope.text = "改变前";            $scope.changeWithoutApply = function() {                setTimeout(function() {                    $scope.text = "改变1";                },1000);            };            $scope.changeWithApply = function() {                setTimeout(function() {                    $scope.$apply(function() {                        $scope.text= "改变2";                    });                },1000);            };        });    </script></body>

这里写图片描述

4. digest循环

  我们已经知道什么时候以及怎么开始digest循环了,那么digest循环具体做了些什么?
  在digest循环中,AngularJS会遍历整个$watch列表,所有watcher都会被触发,当一个wathcer被触发时,AngularJS会检测Scope模型相应的数据,如果它发生了变化,那么关联到该watcher的回调函数就会被触发。
  如果执行了一次digest循环后某个值发生了变化,那么AngularJS会再次循环,直至不再有任何变化。这是因为你在$watch中更新某个值,如果该值对应的$watch已在这遍循环通过,AngularJS将检测不到变化无法更新。如果循环运行了10次或更多次,AngularJS会抛出异常并停止。(就算没有更新值,AngularJS也会多运行一次来确保没有改变,也就是至少运行两次)。

3 0
原创粉丝点击