数据绑定示例
<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 添加了一个观察者
- {{表达式}} - 在你的模板中(以及其他任何有表达式的地方)或我们定义 ng-model 时。
- $ scope。$ watch(’expression / function’) - 在你的 JavaScript 中,我们可以附加一个范围对象来观察角度。
$ watch 函数有三个参数:
- 第一个是观察者函数,它只返回对象,或者我们可以添加一个表达式。
- 第二个是侦听器函数,当对象发生更改时将调用该函数。DOM 更改等所有内容都将在此函数中实现。
- 第三个是可选参数,它接受一个布尔值。如果它是真的,有角度的深度观察对象&如果它的假角度只是做一个参考观察对象。 $ 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();
}
};