为什么 AngularJS 在每个摘要循环中执行函数?

Why does AngularJS execute function on every digest loop?

我来自 Knockout,我正在尝试了解 Angular 如何更新范围。我有点困惑为什么在作用域上定义的函数(例如 $scope.doStuff = function())在每次作用域刷新时都会执行。

Plnkr link: http://plnkr.co/edit/YnvOELGkRbHOovAWPIpF?p=preview

例如:

HTML

<div ng-controller="one">
  <input type="text" ng-model="a">
  {{b()}}
</div>

JS

angular.module('test', [])
 .controller('one', ['$scope', function ($scope) {
   $scope.a = 'one';
   $scope.b = function () {
     console.log('b has executed');
   }
}])

因此,每当 $scope.a 的输入表单字段中发生事件时,都会执行函数 $scope.b。为什么会这样?那个函数没有依赖,一直刷新好像效率不高

如果我在相同的结构中添加另一个控制器,如下所示:

HTML

<div ng-controller="one">
  <input type="text" ng-model="a">
  {{b()}}
</div>
<div ng-controller="two">
  <input type="text" ng-model="x">
  {{y()}}
</div>

JS

angular.module('test', [])
.controller('one', ['$scope', function ($scope) {
  $scope.a = 'one';
  $scope.b = function () {
    console.log('b has executed');
  }
}])

.controller('two', ['$scope', function ($scope) {
  $scope.x = 'two';
  $scope.y = function () {
    console.log('y has executed');
  }
}])

每次我在控制器 one 中更新 $scope.a 时,输出是:

b has executed
y has executed

为什么控制器 two 正在执行 $scope.y?我认为创建一个新的控制器会创建一个新的子范围。是因为子作用域被 link 编辑到父作用域了吗?

更有趣的是,如果我在控制器 two 中更新 $scope.x 那么输出是:

b has executed
y has executed
b has executed <-- a second time... what?

为什么函数 $scope.b 被执行了第二次?

那么为什么 Angular 中的函数会在每次作用域刷新时执行?

仅仅是因为不可能知道一个函数的所有依赖项是什么。假设您的函数 b(在控制器 one 上)是这样的:

  $scope.b = function () {
    console.log('b has executed');
    another_func($scope);
  }

函数 another_func 的定义是这样的:

function another_func (obj) { 
    obj.a = 'something';
    return obj.a;
}

您如何以编程方式知道函数 $scope.b 将调用一个函数,该函数将调用另一个函数来获取依赖于 $scope.a 的值?

Angular 使用所谓的脏检查。为了保持视图和控制器之间的绑定,必须验证绑定到函数的任何变量。

像您演示的那样使用通常不是一个好主意,并且会影响中型到大型应用程序的性能。

建议使用固定变量绑定到视图并在需要时更改,这将带来更高的整体性能并且只重新渲染已更改的部分。

一般来说,您不会 'call' 视图中的函数,但有时这是唯一的方法,如果在 ng-repeat 中使用动态数据,那么我会将该数据放入 object/array 和 return object/array,那么即使 angular 将继续在其摘要循环中调用该函数,如果不更改,它也不会 'update' 视图。

这里我是这样认为的,每次页面加载时,angular js 都会启动该函数,这意味着每次页面加载时都会执行,所以不要直接调用,使用 ng-change 调用它.

<div ng-controller="one">
  <input type="text" ng-model="a" ng-change=b()>

 </div>
 <div ng-controller="two">
  <input type="text" ng-model="x" ng-change=y()>
</div>

并且在控制器中,您可以按如下方式将该功能分配给所需的 ng-model,

angular.module('test', [])
.controller('one', ['$scope', function ($scope) {

  $scope.b = function () {
 $scope.a = 'one';

console.log('b has executed');
  }
}])

.controller('two', ['$scope', function ($scope) {

 $scope.y = function () {
  $scope.x = 'two';
  console.log('y has executed');
   }
  }]) 

否则您也可以通过分配给 ng-model return 函数值给您的 ng-model,它会给出您的正确答案,而不是每次都调用。