在以下代码中,是否只创建了一个$ watch,即使<input>
元素和双重cur {{customer.name}}
的插值会创建两个与$scope.customer.name
不同的绑定?
<html ng-app>
<body>
<input ng-model="customer.name" />
{{customer.name}}
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.2.12/angular.min.js"></script>
</body>
</html>
作为后续跟踪,对$ watch中定义的侦听器的最终回调是否会更新DOM并重新呈现这些已更改的元素?
答案 0 :(得分:1)
每个ng- *和angular表达式在内部创建一个单独的观察者。 如果要检查创建了多少观察者,可以检查角度私有范围属性范围。$$观察者
有时可能会有很多针对复杂应用程序的观察者,有一些性能问题,这就是为什么库Bindonce诞生了(在演示中你可以找到有趣的代码来检查观察者)
答案 1 :(得分:1)
将会增加两名观察员。
略微简化,观察者是一个添加到范围$$观察者数组的对象。这个观察者对象有一个watchFunction和一个listenerFunction。
即使您使用$watch
两次注册同一对watch- and listenerFunction,也会添加两个观察者对象。
这取决于观察者。
考虑示例中的插值:{{ customer.name }}
关联监视对象的listenerFunction(在监视表达式已更改时执行的函数)将如下所示:
function interpolateFnWatchAction(value) {
node[0].nodeValue = value;
}
非常简单。 listenerFunction将使用新值更新节点的nodeValue。当Angular的摘要循环完成后,执行将离开Angular和JavaScript上下文,然后浏览器重新呈现DOM以反映更改。再简单一点。
当谈到ng-model指令时,它变得更复杂,因为它具有双向数据绑定($ scope - &gt; view和view - &gt; $ scope),而前一个案例有一个单向数据绑定($ scope - &gt; view)。
从ng-model添加的观察者甚至没有注册listenerFunction。相反,它在watchFunction中执行。
我不会更深入地讨论这个问题,但不妨把下面的代码放在那里(可以找到here):
$scope.$watch(function ngModelWatch() {
var value = ngModelGet($scope);
// if scope model value and ngModel value are out of sync
if (ctrl.$modelValue !== value) {
var formatters = ctrl.$formatters,
idx = formatters.length;
ctrl.$modelValue = value;
while (idx--) {
value = formatters[idx](value);
}
if (ctrl.$viewValue !== value) {
ctrl.$viewValue = ctrl.$$lastCommittedViewValue = value;
ctrl.$render();
}
}
return value;
});