我应该始终将函数绑定到$ scope对象吗?

时间:2013-02-22 07:14:48

标签: javascript angularjs

当我创建控制器时,我总是向$scope对象添加函数,如下所示:

function DummyController($scope) {

  $scope.importantFunction = function () { /*...*/ };

  $scope.lessImportantFunction = function () { /*...*/ };

  $scope.bussinessLogicFunction = function () { /*...*/ };

  $scope.utilityFunction = function () { /*...*/ };

}

当然,我保持我的控制器封装良好,确保业务逻辑位于适当的组件(通过DI注入)或服务。因此,控制器专注于在UI和后端之间编排事物。

但是,正如您所看到的 - 仍有许多不同类型的功能。我喜欢保留更多,因为它提高了可读性恕我直言。

问题 将大量函数附加到$ scope对象是一种很好的做法吗?它有性能开销吗?我知道$scope是一种特殊的对象,在Angular的摘要周期中经常被评估,所以我这样做是正确还是我会坚持我的方法来解决问题?

(请注意:我不是在寻找替代方法。我正在寻找对知道Angular内部人员的深思熟虑的分析。)

THX!

更新:

安德斯的回答非常好,并向您展示了一些可以遵循的道路。今天我遇到了这个美女,chrome extension for Angular Js debugging and performance monitoring。它显示了所有范围和分配的变量,以及一些有趣的性能图。任何Angular开发者都必须拥有!

1 个答案:

答案 0 :(得分:16)

更新

  1. 我应该将所有功能和变量添加到示波器吗?

    不,如果您需要在模板中访问它们,则只应在范围中添加函数和变量。仅在控制器功能中访问的变量不应位于范围内,它应该是控制器功能的本地变量。

  2. 如果我在示波器中添加了很多功能会影响性能吗?

    一般来说,没有。范围上执行的函数(如ng-click="myFunction()")不应以明显的方式影响性能。但是如果您的函数执行如下:{{myFunction()}}它将针对每个摘要执行,因为Angular需要知道它的返回值是否已更改,以便它可以更新UI。

  3. 如果我在范围中添加了很多变量会影响效果吗?

    如果您在Angular会检查它们的地方使用它们会影响性能。如果您在{{myVariable}}ng-model="myVariable"等中使用它们,则会将这些情况打印出来,例如ng-show="myVariable",等ng-click等指令不执行脏检查,因此不会不要放慢速度。 Angular背后的人建议你不要在一个页面上使用超过2000个表达式,这些表达式需要重新绘制/脏检查,因为你的性能将在此之后开始降级。 2000年的极限是他们在研究Angular中的性能时发现的。

    请注意,仅仅因为您在作用域上添加了属性,并不意味着Angular将对其执行脏检查。它们必须在您的模板中用于执行脏检查(但不能用于ng-click)。

  4. 如果我想在Angular应用中获得最佳性能,我应该注意什么?

    就像我上面提到的,尝试将绑定模板表达式的数量保持在2000以下。如果在作用域上实现监视,请确保监视的表达式执行得非常快。这是一个如何不应该这样做的例子:

    $scope.items = [];
    for (var i = 0; i < 1000; i++) {
        $scope.items.push({prop1: 'val1', prop2: 'val2', prop3: 'val3'});
    }
    
    $scope.$watch('items', function() {
    
    }, true);
    

    通过将true作为第三个参数添加到$ watch,您告诉Angular在每个摘要周期中循环$scope.items以检查千个项目中的任何属性是否已更改,这将是在时间和记忆上都是昂贵的。

    你应该做的是:

    $scope.items = [];
    for (var i = 0; i < 1000; i++) {
        $scope.items.push({prop1: 'val1', prop2: 'val2', prop3: 'val3'});
    }
    
    $scope.$watch('items.length', function() {
    
    });
    

    也就是说,只检查$scope.items.length何时发生变化。该表达式将很快执行。


  5. 原帖:

    如果你的问题是“将函数暴露给模板比使用对象更好”,那么是的,你应该尽可能多地使用函数。这样你就可以将逻辑封装在控制器中,而不是让它流入你的模板。举个例子:

    <div ng-show="shouldShow">Toggled div</div>
    <button ng-click="shouldShow = !shouldShow">Toggle<button>
    

    这里的模板对发生的事情有太多的了解。相反,这应该像这样解决:

    // controller
    var shouldShow = false;
    scope.toggle = function() {
        shouldShow = !shouldShow;
    }
    scope.shouldShow = function() {
        return shouldShow;
    }
    
    <!-- template -->
    <div ng-show="shouldShow()">Toggled div</div>
    <button ng-click="toggle()">Toggle<button>
    

    通过这样做,在不触及模板的情况下扩展控制器中的逻辑是微不足道的。虽然您现在的要求可能只是在按下按钮时切换div,但明天的要求可能是在发生这种情况时更新应用程序的其他部分。如果您使用函数,则很容易在函数内添加该逻辑而无需更改模板。

    范围上的函数比使用属性有更多的开销,但是当这一天到来时,这种开销可能不会降低你的应用程序的速度。所以在有意义时使用函数。

    但是你仍然应该尽量保持你的控制器尽可能小。如果它们增长到包含大量功能/功能,您可能应该将控制器拆分为可重复使用的指令。