1. AngularJS的双向数据绑定,使model变更都会被反映到view中。对于检查绑定的数据到底有没有发生变化,实际上是由scope.digest()完成的,但是我们几乎从来就没有直接调用过这个方法,而是调用scope.apply()方法,是因为在scope.apply()方法里面,它会去调用scope.digest()方法。scope.apply()方法带一个函数或者一个表达式,然后执行它,最后调用scope.digest()方法去更新bindings或者watchers。除了ng-click指令,还有一些其它的built-in指令以及服务来让你更改models(比如ng-model,$timeout等)和自动触发一次$digest循环.
2. $scope.$apply()会自动地调用$rootScope.$digest()。$apply()方法有两种形式。
第一种会接受一个function作为参数,执行该function并且触发一轮$digest循环。
第二种会不接受任何参数,只是触发一轮$digest循环。
3. 但是,如果你在AngularJS上下文之外的任何地方修改了model,那么你就需要通过手动调用$apply()来通知AngularJS。
比如,如果你使用了JavaScript中的setTimeout()来更新一个scope model,那么AngularJS就没有办法知道你更改了什么.调用$apply()就是你的责任了,通过调用它来触发一轮$digest循环。
我们不应该这样做,而是用angular JS提供的timeout方法,这样它就会被自动用apply方法包起来了。
方式1" $scope.getMessage = function() { setTimeout(function() { $scope.$apply(function() { //wrapped this within $apply $scope.message = 'Fetched after 3 seconds'; console.log('message:' + $scope.message); }); }, 2000); } 方式2: $scope.getMessage = function() { setTimeout(function() { $scope.message = 'Fetched after two seconds'; console.log('message:' + $scope.message); $scope.$apply(); //this triggers a $digest }, 2000); }; 方式3: $timeout.cancel(scope.t2); scope.t1 = $timeout(function(){ scope.ifShowMenu = true },500)
类似地,如果你有一个指令用来设置一个DOM事件listener并且在该listener中修改了一些models,那么你也需要通过手动调用$apply()来确保变更会被正确的反映到view中。
4. Scope提供$watch方法监视Model的变化。
Scope提供$apply方法传播Model的变化。
Scope可以继承,用来隔离不同的application components和属性访问权限。
Scope为Expressions的计算提供上下文。
5. 还是那个问题,那我们到底什么时候需要去调用apply()方法呢?情况非常少,实际上几乎我们所有的代码都包在scope.apply()里面,像ng−click,controller的初始化,http的回调函数等。在这些情况下,我们不需要自己调用,实际上我们也不能自己调用,否则在apply()方法里面再调用apply()方法会抛出错误。
如果我们需要在一个新的执行序列中运行代码时才真正需要用到它,而且当且仅当这个新的执行序列不是被angular JS的库的方法创建的,这个时候我们需要将代码用scope.apply()包起来。