Angular会创建一个新的观察者(如果已经存在)吗?

时间:2015-07-22 17:18:44

标签: angularjs

考虑:

angular
  .module('app', [])
  .controller('MainController', function($scope) {
    $scope.$watch('bool', function(newVal, oldVal) {
    });
    console.log($scope);
  });

<body ng-controller='MainController'>
  <p ng-class="{'blue': bool, 'red': !bool}">ngClass</p>
  <p ng-show='bool'>ngShow</p>
  <input type='checkbox' ng-model='bool' />
</body>

plnkr of above

似乎有3位观察者正在创建:

  1. 来自$scope.$watch
  2. 来自ngShow
  3. 来自ngClass
  4. (注意:涉及数据绑定的指令use $ scope。$ watch inside。)

    enter image description here

    我原以为,因为他们都在观看bool属性,所以只有一个观察者,并且它有多个监听器回调。

    编辑:它是否会说,&#34; bool已更改?如果是,请运行cb1bool已更改?如果是,请运行cb2bool已更改?如果是,请运行cb3。&#34;或者是它的说法,&#34;已经bool改变了吗?如果是,请运行cb1cb2cb3。&#34;如果是前者,为什么会这样呢?

    问题:

    1. 我的解释是否正确?实际上是否有多个手表被注册?
    2. 对绩效有何影响?
    3. 奖励:如果我的解释是正确的并且添加了多个观察者,为什么会这样设计呢?为什么要查找bool 3次而不是1次?
    4. 的更改

      示例2) - 假设您要确保表单中的两个密码匹配,如果不是,则显示错误。假设你已经拥有:

      ng-class="{invalid: myForm.myInput1.$touched && ctrl.myInput1  != ctrl.myInput2}" 
      

      假设您要使用$setValidity更新表单的有效性。这可能是个好主意:

      ng-class="{invalid: myForm.myInput1.$touched && ctrl.functionToCheckInputs(myForm)}"
      

      并在$setValidity内拨打functionToCheckInputs而不是使用$scope.$watch并在其中执行$setValidity?因为后者增加了额外的观察者(大概)。

5 个答案:

答案 0 :(得分:3)

有多个$ watchers正在注册。事实上,即使你有两个确切的表达式:

$scope.$watch("foo", cb1)
$scope.$watch("foo", cb2)

你仍然会得到2美元的观察者。

要回答您的问题 - 这是前一种情况,即“如果"foo"表达式更改,运行cb1"foo"表达式更改,运行cb2等。 ..为什么?因为,任何$ watcher都可能改变$scope.foo的返回值;不仅仅是在回调中,而是在表达式本身中.Angular需要每次重新计算表达式以解释这种可能性。

摘要周期的长度对性能起着重要影响。

首先,是$ watchers的数量,这会导致观察的表达式或函数进行评估。因此,减少观看者的数量,比如喜欢单向观看,或者在合适的地方使用一次性观看,可以提高性能。

第二,是观看功能的复杂性。这些功能应该非常快 - 理想情况下,不仅仅是吸气剂。例如,请避免以下情况:

<div ng-class="{active: isActive(id)}">
$scope.isActive = function(id){
   for (var i=0; i<items.length; i++){
      if (items[i].id == id && items[0].active) return true;
   }
   return false;
};

答案 1 :(得分:2)

我的解释是否正确?实际上是否有多个手表被注册?

所以为了回答这个问题,我回过头来看另一篇非常好的堆栈文章。 How to count total number of watches on a page?

当将countWatchers方法添加到ngMock模块时,这是很好的预角度AngularJS 1.3.2。

现在您可以计算项目上的手表数量,这是正确的,有3个双向关系已经创建,将会观看。

对效果有何影响?

这有点难以量化,观察者越多,其表现就越差。我的建议是使用Batarang判断你的观察者的表现,以确保你不会膨胀你的应用程序。 https://chrome.google.com/webstore/detail/angularjs-batarang-stable/niopocochgahfkiccpjmmpchncjoapek

在我自己的个人应用程序中,当我注意到重大的性能问题时,大约有2000个手表。

奖励:如果我的解释是正确的并且添加了多个观察者,为什么会这样设计?为什么要寻找bool 3次而不是1次的变化?

观看由双向关系组成。这是角度的斗争之一,因为有一种快速的方式,以角度和更优化的方式做某事。如果您已将该标记作为模板中使用bool的指令,则只有1个指针链接到该指令。 Angular 2.0应该改进这一点。

答案 2 :(得分:1)

许多变量同时在单个手表中使用..如果进行任何更改,则调用手表功能

.remove-check

答案 3 :(得分:0)

是。

   $scope.$watch('bool', function(newVal, oldVal) {    
   console.log("bool changed");
   });

   $scope.$watch('bool2', function(newVal, oldVal) {
       console.log("bool2 changed");
   });

答案 4 :(得分:0)