这个答案有两个部分,第一部分是回答哪个是更好的选择,另一部分是它们都不是一个好的选择!
哪一个是正确的?
这个是:
$scope.addToDo = function(params1, ...) {
alert(params1);
}
为什么?因为 A - 它是可测试的。即使您不编写测试,这也很重要,因为从长远来看,可测试的代码几乎总是更具可读性和可维护性。
由于 B,它也更好 - 它对于调用者是不可知的。此功能可以被任意数量的不同控制器/服务/等重用,因为它不依赖于范围的存在或该范围的结构。
当您改为这样做时:
$scope.addToDo = function() {
alert($scope.params1);
}
A 和 B 都失败了。它本身不容易测试,也不容易被重用,因为你使用它的范围可能有不同的格式。
编辑:如果您正在做与您的特定范围密切相关的事情并从模板运行函数,那么您可能会遇到试图使其可重用的情况没有意义。该功能根本不是通用的。在这种情况下,请不要为此烦恼,某些功能无法重用。查看我所写的作为您的默认模式的内容,但请记住,在某些情况下它不适合。
为什么两个都错了?
因为作为一般规则,您不应该在控制器中执行逻辑,这是服务的工作。控制器可以使用服务并调用该函数或在模型中公开它,但不应定义它。
为什么这很重要?因为它再次使重用该功能变得容易。在控制器中定义的函数不能在另一个控制器中重用,除非限制控制器在 HTML 中的调用方式。在服务中定义的函数可以在任何你喜欢的地方注入和重用。
但我不需要重用该功能!- 是的你是!也许不是现在,也许永远不会用于这个特定的功能,但迟早你会想要重用一个你确信永远不需要重用的功能。然后你将不得不重新编写你已经忘记一半的代码,这总是需要额外的时间。
最好从一开始就正确地做这件事,并将所有你可以做的逻辑转移到服务中。这样,如果您在其他地方(甚至在另一个项目中)需要它们,您可以抓住它并使用它,而无需重写它以适应您当前的范围结构。
当然,服务不知道你的范围,所以你不得不使用第一个版本。奖金!并且不要陷入将整个范围传递给服务的诱惑,这将永远不会结束:-)
所以这是 IMO 最好的选择:
app.service('ToDoService', [function(){
this.addToDo = function(params1, ...){
alert(params1);
}
}]);
在控制器内部:
$scope.addToDo = ToDoService.addToDo;
请注意,我写的是“一般规则”。在某些情况下,在控制器本身而不是服务中定义功能是合理的。一个例子是当函数只与范围特定的事物相关时,比如以某种方式切换控制器中的状态。没有真正的方法可以在服务中做到这一点而不会让事情变得奇怪。
但听起来这里不是这种情况。