浅谈AngularJs 双向绑定原理(数据绑定机制)(2)


$digest

当浏览器接收到可以被angular context处理的事件时,$digest循环就会触发。$digest将会遍历我们的$watch,如果$watch没有变化,这个循环检测就将停止,如果有至少一个更新过,这个循环就会再次触发,直到所有的$watch都没有变化。这样就能够保证每个model都已经不会再变化。这就是脏检查(Dirty Checking)机制

controller.js

app.controller('MainCtrl', function() {
 $scope.name = "Foo";

 $scope.changeFoo = function() {
  $scope.name = "Bar";
 }
});

index.js

<div>{{ name }}</div>
<button ng-click="changeFoo()">Change the name</button>
  1. 当我们按下按钮
  2. 浏览器接收到一个事件,进入angular context。
  3. $digest循环开始执行,查询每个$watch是否变化。
  4. 由于监视$scope.name的$watch报告了变化,它会强制再执行一次$digest循环。
  5. 新的$digest循环没有检测到变化。
  6. 更新与$scope.name新值相应部分的DOM。

$apply

$apply 我们可以直接理解为刷新UI。<font color=red>如果当事件触发时,你调用$apply,它会进入angular context,如果没有调用就不会进入,之后的$digest检测机制就不会触发</font>

app.directive('clickable', function() {
 return {
  restrict: "E",
  scope: {
  foo: '='
  },
  template: '<ul style="background-color: lightblue"><li>{{foo}}</li></ul>',
  link: function(scope, element, attrs) {
  element.bind('click', function() {
   scope.foo++;
   console.log(scope.foo);
  });
  }
 }
});

当我们调用clickable指令的时候,我们可以看到foo的值增加了,但是界面上显示的内容并没有改变。$digest脏检测机制没有触发,检测foo的$watch就没有执行。

$apply()方法的两种形式

1) 无参

$scope.$apply();
element.bind('click', function() {
 scope.foo++;
 //if error
 scope.$apply();
});

当我们使用这种形式的时候,如果在scope.$apply之前程序发生异常,那scope.$apply没有执行,界面就不会更新

2) 有参

$scope.$apply(function(){
 ...
})
element.bind('click', function() {
 scope.$apply(function() {
  scope.foo++;
 });
})

如果用这种形式,即使后面的发生异常,数据还是会更新。

在 AngularJS 中使用 $watch

常用的使用方式:

$scope.name = 'Hello';
$scope.$watch('name', function(newValue, oldValue) {
 if (newValue === oldValue) { return; } 
 $scope.updated++;
});
      

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:http://www.heiqu.com/534.html