无论有多少DOM元素绑定到监视的$ scope,是否只创建了一个$ watch?

时间:2014-05-12 19:32:17

标签: angularjs angularjs-scope

在以下代码中,是否只创建了一个$ 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并重新呈现这些已更改的元素?

2 个答案:

答案 0 :(得分:1)

每个ng- *和angular表达式在内部创建一个单独的观察者。 如果要检查创建了多少观察者,可以检查角度私有范围属性范围。$$观察者

有时可能会有很多针对复杂应用程序的观察者,有一些性能问题,这就是为什么库Bindonce诞生了(在演示中你可以找到有趣的代码来检查观察者)

答案 1 :(得分:1)

回答问题1:

将会增加两名观察员。

略微简化,观察者是一个添加到范围$$观察者数组的对象。这个观察者对象有一个watchFunction和一个listenerFunction。

即使您使用$watch两次注册同一对watch- and listenerFunction,也会添加两个观察者对象。

回答问题2:

这取决于观察者。

考虑示例中的插值:{{ 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;
});