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

时间:2015-04-06 15:38:42

标签: javascript angularjs knockout.js scope angularjs-scope

我来自Knockout,我试图了解Angular如何更新范围。关于为什么在范围上定义的函数(例如$scope.doStuff = function())在每个范围刷新时都会被执行,我感到有点困惑。

Plnkr链接: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');
  }
}])

每当我更新控制器$scope.a中的one时,输出为:

b has executed
y has executed

为什么控制器two正在执行$scope.y?我认为创建一个新的控制器会创建一个新的子范围。是因为子范围与父范围相关联吗?

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

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

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

那么为什么Angular中的函数会在每个范围刷新时执行?

3 个答案:

答案 0 :(得分:3)

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

使用你所演示的内容通常是一个坏主意,可以影响中型到大型应用程序的性能。

使用固定变量绑定到视图并在需要时进行更改时,这将导致整体性能更高,并且仅重新渲染已更改的部分。

一般情况下,你不从视图中“调用”该函数,但有时这是在ng-repeat中使用动态数据的唯一方法然后我会将该数据放入一个对象/数组并返回该对象/数组,然后甚至角度将继续在其摘要周期上调用该函数,如果不更改它将不会“更新”视图。

答案 1 :(得分:2)

在这里我这么认为,每次页面加载时,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模型,如下所示,

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将函数值返回到ng-model,它将给出正确答案而不是每次调用。

答案 2 :(得分:1)

只是因为无法知道函数的所有依赖项是什么。假设您的函数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的值?