当我创建控制器时,我总是向$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开发者都必须拥有!
答案 0 :(得分:16)
更新
我应该将所有功能和变量添加到示波器吗?
不,如果您需要在模板中访问它们,则只应在范围中添加函数和变量。仅在控制器功能中访问的变量不应位于范围内,它应该是控制器功能的本地变量。
如果我在示波器中添加了很多功能会影响性能吗?
一般来说,没有。范围上执行的函数(如ng-click="myFunction()"
)不应以明显的方式影响性能。但是如果您的函数执行如下:{{myFunction()}}
它将针对每个摘要执行,因为Angular需要知道它的返回值是否已更改,以便它可以更新UI。
如果我在范围中添加了很多变量会影响效果吗?
如果您在Angular会检查它们的地方使用它们会影响性能。如果您在{{myVariable}}
,ng-model="myVariable"
等中使用它们,则会将这些情况打印出来,例如ng-show="myVariable"
,等ng-click
等指令不执行脏检查,因此不会不要放慢速度。 Angular背后的人建议你不要在一个页面上使用超过2000个表达式,这些表达式需要重新绘制/脏检查,因为你的性能将在此之后开始降级。 2000年的极限是他们在研究Angular中的性能时发现的。
请注意,仅仅因为您在作用域上添加了属性,并不意味着Angular将对其执行脏检查。它们必须在您的模板中用于执行脏检查(但不能用于ng-click)。
如果我想在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
何时发生变化。该表达式将很快执行。
原帖:
如果你的问题是“将函数暴露给模板比使用对象更好”,那么是的,你应该尽可能多地使用函数。这样你就可以将逻辑封装在控制器中,而不是让它流入你的模板。举个例子:
<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,但明天的要求可能是在发生这种情况时更新应用程序的其他部分。如果您使用函数,则很容易在函数内添加该逻辑而无需更改模板。
范围上的函数比使用属性有更多的开销,但是当这一天到来时,这种开销可能不会降低你的应用程序的速度。所以在有意义时使用函数。
但是你仍然应该尽量保持你的控制器尽可能小。如果它们增长到包含大量功能/功能,您可能应该将控制器拆分为可重复使用的指令。