wordpress在百度排名靠前seo经验是什么
双向数据绑定(Two-way Data Binding),这个特性大大简化了我们的代码编写方式。数据绑定意味着当View中有任何数据发生了变化,那么这个变化也会自动地反馈到scope的数据上,也即意味着scope模型会自动地更新。类似地,当scope模型发生变化时,view中的数据也会更新到最新的值。
当你写下表达式如{{ aModel }}时,AngularJS在幕后会为你在scope模型上设置一个watcher,它用来在数据发生变化的时候更新view。
这里的watcher和你会在AngularJS中设置的watcher是一样的:
$scope.$watch('aModel', function(newValue, oldValue) {//update the DOM with newValue
});
传入到$watch()中的第二个参数是一个回调函数,该函数在aModel的值发生变化的时候会被调用来更新view。
digest循环:它会周期性的运行一个函数来检查scope模型中的数据是否发生了变化.在digest循环中,watchers会被触发。当一个watcher被触发时,AngularJS会检测scope模型,如何它发生了变化那么关联到该watcher的回调函数就会被调用。
在调用了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循环。
AngularJS并不直接调用digest(),而是调用scope.apply(),后者会调用rootScope.digest()。因此,一轮digest循环在$rootScope开始,随后会访问到所有的children scope中的watchers。
scope.apply()会自动地调用rootScope.digest()。apply()方法有两种形式。
第一种会接受一个function作为参数,执行该function并且触发一轮digest循环。(推荐)
第二种会不接受任何参数,只是触发一轮digest循环。
需要记住的是你总是应该使用接受一个function作为参数的apply()方法。这是因为当你传入一个function到apply()中的时候,
这个function会被包装到一个try…catch块中,所以一旦有异常发生,该异常会被$exceptionHandler service处理。
什么时候手动调用apply()方法?
实际上,AngularJS对此有着非常明确的要求,就是它只负责对发生于AngularJS上下文环境中的变更会做出自动地响应(即,在apply()方法中发生的对于models的更改)。AngularJS的built-in指令就是这样做的,所以任何的model变更都会被反映到view中。
但是,如果你在AngularJS上下文之外的任何地方修改了model,那么你就需要通过手动调用$apply()来通知AngularJS。这就像告诉AngularJS,你修改了一些models,希望AngularJS帮你触发watchers来做出正确的响应。
比如,如果你使用了JavaScript中的setTimeout()来更新一个scope model,那么AngularJS就没有办法知道你更改了什么。这种情况下,调用apply()就是你的责任了,通过调用它来触发一轮digest循环。类似地,如果你有一个指令用来设置一个DOM事件listener并且在该listener中修改了一些models,那么你也需要通过手动调用apply()来确保变更会被正确的反映到view中。
digest循环会运行多少次?
当一个digest循环运行时,watchers会被执行来检查scope中的models是否发生了变化。如果发生了变化,那么相应的listener函数就会被执行。这涉及到一个重要的问题。如果listener函数本身会修改一个scope model呢?AngularJS会怎么处理这种情况?
答案是digest循环不会只运行一次。在当前的一次循环结束后,它会再执行一次循环用来检查是否有models发生了变化。这就是脏检查(Dirty Checking),它用来处理在listener函数被执行时可能引起的model变化。因此,digest循环会持续运行直到model不再发生变化,或者digest循环的次数达到了10次。因此,尽可能地不要在listener函数中修改model。
digest循环最少也会运行两次,即使在listener函数中并没有改变任何model。正如上面讨论的那样,它会多运行一次来确保models没有变化。
需要记住的最重要的是AngularJS是否能检测到你对于model的修改。如果它不能检测到,那么你就需要手动地调用apply()。
例子如下:
timeout service:
angularjs服务:会帮你调用apply(),让你不需要手动地调用它。
setTimeout()
Javascript方法,需要手动调用apply
<!DOCTYPE html>
<html ng-app="myApp">
<head><meta charset="utf-8"><title>My AngularJS App</title><script src="http://sandbox.runjs.cn/uploads/rs/376/pbcx3e1z/angular.min.js"></script><script src="http://sandbox.runjs.cn/uploads/rs/376/pbcx3e1z/angular-route.min.js"></script>
</head><body>
<div ng-controller="MessageController1">Delayed Message: {{message}};
</div>
<div ng-controller="MessageController2">Delayed Message: {{message}};
</div>
<div ng-controller="MessageController3">Delayed Message: {{message}};
</div><script>angular.module('myApp', [])/*$timeout service:angularjs服务:会帮你调用$apply(),让你不需要手动地调用它。* setTimeout() :Javascript方法,需要手动调用$apply*/.controller('MessageController1', function ($scope) {$scope.getMessage = function () {setTimeout(function () {$scope.message = ' setTimeout===Fetched after two seconds';console.log('message:js1' + $scope.message);$scope.$apply();//this triggers a $digest第二种会不接受任何参数,只是触发一轮$digest循环。}, 2000);};$scope.getMessage();}).controller('MessageController2', function ($scope) {$scope.getMessage = function () {setTimeout(function () {$scope.$apply(function () {//第一种会接受一个function作为参数,执行该function并且触发一轮$digest循环。(推荐)//wrapped this within $apply$scope.message = ' setTimeout==Fetched after 2 seconds';console.log('message:js2' + $scope.message);});}, 2000);};$scope.getMessage();}).controller('MessageController3', function ($scope, $timeout) {$timeout(function () {/*内置服务自动调用$apply*/$scope.message = ' $timeout===Fetched after two seconds';console.log('message:ng' + $scope.message);}, 2000);});</script>
</body>
</html>
以上三种写法一样的效果:
参考:
理解Angular中的apply()以及digest()