数据绑定示例

<p ng-bind="message"></p>

消息必须附加到当前元素控制器的范围。

$scope.message = "Hello World";

在以后的某个时间点,即使更新了消息模型,该更新的值也会反映在 HTML 元素中。当角度编译模板时,Hello World 将附加到当前世界的 innerHTML。Angular 维护着一个附加到视图的所有指令的监视机制。它有一个 Digest Cycle 机制,它遍历 Watchers 数组,如果模型的先前值发生变化,它将更新 DOM 元素。

没有定期检查 Scope 是否附加的对象有任何变化。并非所有附加到范围的对象都被观看。范围原型维护 $$ WatchersArray 。只有在调用$ digest 时,Scope 才会遍历此 WatchersArray。

Angular 为 WatchersArray 添加了一个观察者

  1. {{表达式}} - 在你的模板中(以及其他任何有表达式的地方)或我们定义 ng-model 时。
  2. $ scope。$ watch(’expression / function’) - 在你的 JavaScript 中,我们可以附加一个范围对象来观察角度。

$ watch 函数有三个参数:

  1. 第一个是观察者函数,它只返回对象,或者我们可以添加一个表达式。
  1. 第二个是侦听器函数,当对象发生更改时将调用该函数。DOM 更改等所有内容都将在此函数中实现。
  1. 第三个是可选参数,它接受一个布尔值。如果它是真的,有角度的深度观察对象&如果它的假角度只是做一个参考观察对象。 $ watch 的粗略实现看起来像这样
Scope.prototype.$watch = function(watchFn, listenerFn) {
   var watcher = {
       watchFn: watchFn,
       listenerFn: listenerFn || function() { },
       last: initWatchVal  // initWatchVal is typically undefined
   };
   this.$$watchers.push(watcher); // pushing the Watcher Object to Watchers  
};

Angular 中有一个有趣的东西叫做 Digest Cycle。 $ digest 循环由于调用$ scope 而开始。$ digest()。假设你通过 ng-click 指令更改处理函数中的$ scope 模型。在这种情况下,AngularJS 通过调用$ digest() 自动触发$ digest 循环。除了 ng-click 之外,还有其他一些内置指令/服务可以让你改变模型(例如 ng-model,$ timeout 等)并自动触发$ digest 循环。 $ digest 的粗略实现看起来像这样。

Scope.prototype.$digest = function() {
      var dirty;
      do {
          dirty = this.$$digestOnce();
      } while (dirty);
}
Scope.prototype.$$digestOnce = function() {
   var self = this;
   var newValue, oldValue, dirty;
   _.forEach(this.$$watchers, function(watcher) {
          newValue = watcher.watchFn(self);
          oldValue = watcher.last;   // It just remembers the last value for dirty checking
          if (newValue !== oldValue) { //Dirty checking of References 
   // For Deep checking the object , code of Value     
   // based checking of Object should be implemented here
             watcher.last = newValue;
             watcher.listenerFn(newValue,
                  (oldValue === initWatchVal ? newValue : oldValue),
                   self);
          dirty = true;
          }
     });
   return dirty;
 };

如果我们使用 JavaScript 的 setTimeout() 函数来更新范围模型,Angular 无法知道你可能会更改什么。在这种情况下,我们有责任手动调用$ apply(),这会触发$ digest 循环。类似地,如果你有一个设置 DOM 事件侦听器的指令并更改处理函数内部的某些模型,则需要调用$ apply() 以确保更改生效。 $ apply 的主要思想是我们可以执行一些不了解 Angular 的代码,该代码可能仍会改变范围内的东西。如果我们将该代码包装在$ apply 中,它将负责调用$ digest()。 $ apply() 的粗略实现。

Scope.prototype.$apply = function(expr) {
       try {
         return this.$eval(expr); //Evaluating code in the context of Scope
       } finally {
         this.$digest();
       }
};