myApp.controller('firstController',function($scope,$interval){ $scope.date = new Date(); setInterval(function(){ $scope.$apply(function(){ scope.date = new Date(); }) },1000) })
Scope提供$watch方法监视Model的变化。
Scope提供$apply方法传播Model的变化。javascript
AngularJS提供了一个很是酷的特性叫作双向数据绑定(Two-way Data Binding),这个特性大大简化了咱们的代码编写方式。数据绑定意味着当View中有任何数据发生了变化,那么这个变化也会自动地反馈到scope的数据上,也即意味着scope模型会自动地更新。相似地,当scope模型发生变化时,view中的数据也会更新到最新的值。那么AngularJS是如何作到这一点的呢?当你写下表达式如{{ aModel }}时,AngularJS在幕后会为你在scope模型上设置一个watcher,它用来在数据发生变化的时候更新view。这里的watcher和你会在AngularJS中设置的watcher是同样的:java
$scope.$watch('aModel', function(newValue, oldValue) { //update the DOM with newValue });
传入到$watch()中的第二个参数是一个回调函数,该函数在aModel的值发生变化的时候会被调用。当aModel发生变化的时候,这个回调函数会被调用来更新view这一点不难理解,可是,还存在一个很重要的问题!AngularJS是如何知道何时要调用这个回调函数呢?换句话说,AngularJS是如何知晓aModel发生了变化,才调用了对应的回调函数呢?它会周期性的运行一个函数来检查scope模型中的数据是否发生了变化吗?好吧,这就是$digest循环的用武之地了。app
在$digest循环中,watchers会被触发。当一个watcher被触发时,AngularJS会检测scope模型,如何它发生了变化那么关联到该watcher的回调函数就会被调用。那么,下一个问题就是$digest循环是在何时以各类方式开始的?函数
在调用了$scope.$digest()后,$digest循环就开始了。假设你在一个ng-click指令对应的handler函数中更改了scope中的一条数据,此时AngularJS会自动地经过调用$digest()来触发一轮$digest循环。当$digest循环开始后,它会触发每一个watcher。这些watchers会检查scope中的当前model值是否和上一次计算获得的model值不一样。若是不一样,那么对应的回调函数会被执行。调用该函数的结果,就是view中的表达式内容(译注:诸如{{ aModel }})会被更新。除了ng-click指令,还有一些其它的built-in指令以及服务来让你更改models(好比ng-model,$timeout等)和自动触发一次$digest循环。ui
目前为止还不错!可是,有一个小问题。在上面的例子中,AngularJS并不直接调用$digest(),而是调用$scope.$apply(),后者会调用$rootScope.$digest()。所以,一轮$digest循环在$rootScope开始,随后会访问到全部的children scope中的watchers。spa
如今,假设你将ng-click指令关联到了一个button上,并传入了一个function名到ng-click上。当该button被点击时,AngularJS会将此function包装到一个wrapping function中,而后传入到$scope.$apply()。所以,你的function会正常被执行,修改models(若是须要的话),此时一轮$digest循环也会被触发,用来确保view也会被更新。.net
Note: $scope.$apply()会自动地调用$rootScope.$digest()。$apply()方法有两种形式。第一种会接受一个function做为参数,执行该function而且触发一轮$digest循环。第二种会不接受任何参数,只是触发一轮$digest循环。咱们立刻会看到为何第一种形式更好。blog
何时手动调用$apply()方法?事件
若是AngularJS老是将咱们的代码wrap到一个function中并传入$apply(),以此来开始一轮$digest循环,那么何时才须要咱们手动地调用$apply()方法呢?实际上,AngularJS对此有着很是明确的要求,就是它只负责对发生于AngularJS上下文环境中的变动会作出自动地响应(即,在$apply()方法中发生的对于models的更改)。AngularJS的built-in指令就是这样作的,因此任何的model变动都会被反映到view中。可是,若是你在AngularJS上下文以外的任何地方修改了model,那么你就须要经过手动调用$apply()来通知AngularJS。这就像告诉AngularJS,你修改了一些models,但愿AngularJS帮你触发watchers来作出正确的响应。ip
好比,若是你使用了JavaScript中的setTimeout()来更新一个scope model,那么AngularJS就没有办法知道你更改了什么。这种状况下,调用$apply()就是你的责任了,经过调用它来触发一轮$digest循环。相似地,若是你有一个指令用来设置一个DOM事件listener而且在该listener中修改了一些models,那么你也须要经过手动调用$apply()来确保变动会被正确的反映到view中。
能够参考:http://blog.csdn.net/dm_vincent/article/details/38705099