Ada*_*mas 23 javascript angularjs
我正在使用TodoMVC应用程序来改进AngularJS框架.在第14-16行的index.html中,您会看到:
<form id="todo-form" ng-submit="addTodo()">
<input id="new-todo" placeholder="What needs to be done?" ng-model="newTodo" autofocus>
</form>
Run Code Online (Sandbox Code Playgroud)
请注意ng-submit指令如何在不将newTodo模型作为参数传递的情况下调用addTodo()函数.
不久之后,我在第19行的同一个文件中遇到了以下代码:
<input id="toggle-all" type="checkbox" ng-model="allChecked" ng-click="markAll(allChecked)">
Run Code Online (Sandbox Code Playgroud)
您可以看到作者此次决定将allChecked模型传递给markAll()函数.如果我理解正确,他们可以在控制器中引用$ scope.allChecked而不是传入它.
为什么在同一个文件中使用两种不同的方法?在某些情况下,一种方法更好吗?这是一个不一致的情况还是使用了更深层次的逻辑?
Kha*_* TO 31
我宁愿总是将参数传递给函数:
考虑以下情况:
$scope.addToDo = function(){
//This declaration is not clear what parameters the function expects.
if ($scope.parameter1){
//do something with parameter2
}
}
Run Code Online (Sandbox Code Playgroud)
更糟糕的是:
$scope.addToDo = function(){
//This declaration is not clear what parameters the function expects.
if ($scope.someobject.parameter1){ //worse
}
}
Run Code Online (Sandbox Code Playgroud)
由于范围继承parameter2可能来自父范围,因此访问parameter2函数内部会产生紧耦合,当您尝试对该函数进行单元测试时也会导致麻烦.
如果我定义这样的函数:
//It's clearer that the function expects parameter1, parameter2
$scope.addToDo = function(parameter1, parameter2){
if (parameter1){
//do something with parameter2
}
}
Run Code Online (Sandbox Code Playgroud)
如果您parameter2继承自父作用域,您仍然可以从视图中传入它.进行单元测试时,很容易传递所有参数.
如果你曾经使用ASP.NET MVC的工作,你会发现类似的东西:框架试图注入参数转化为行动的功能,而不是直接访问它Request或HttpContext对象
如果其他人提到喜欢和他人一起工作,那也很好 ng-repeat
在我看来,角度控制器和模型并没有很清楚地分开.$ scope对象看起来像我们的Model,带有属性和方法(Model也包含逻辑).来自OOP背景的人会认为:我们只传递不属于对象的参数.就像Person已有的类一样hands,我们不需要hands为每个对象方法传入.像这样的示例代码:
//assume that parameter1 belongs to $scope, parameter2 is inherited from parent scope.
$scope.addToDo = function(parameter2){
if ($scope.parameter1){ //parameter1 could be accessed directly as it belongs to object, parameter2 should be passed in as parameter.
//do something with parameter2
}
}
Run Code Online (Sandbox Code Playgroud)
这个答案有两个部分,第一部分是回答哪一个是更好的选择,另一部分是这两个部分都不是一个好的选择!
哪一个是正确的?
这个是:
$scope.addToDo = function(params1, ...) {
alert(params1);
}
Run Code Online (Sandbox Code Playgroud)
为什么?因为A - 它是可测试的.即使您没有编写测试,这也很重要,因为从长远来看,可测试的代码几乎总是更易读和可维护.
它也更好,因为B - 它对呼叫者来说是不可知的.此函数可以由任意数量的不同控制器/服务/等重用,因为它不依赖于作用域的存在或该作用域的结构.
当你这样做时:
$scope.addToDo = function() {
alert($scope.params1);
}
Run Code Online (Sandbox Code Playgroud)
A和B都失败了.它本身不易测试,并且不能轻易地重复使用,因为您使用它的范围可能有不同的格式.
编辑:如果您正在执行与特定范围密切相关的操作并从模板运行该功能,那么您可能会遇到尝试使其可重用但没有意义的情况.该功能根本不是通用的.在这种情况下,请不要理会,某些功能无法重复使用.查看我写的关于默认模式的内容,但请记住,在某些情况下它不适合.
为什么两个都错了?
因为作为一般规则,您不应该在控制器中执行逻辑,这是服务的工作.控制器可以使用服务并调用函数或在模型中公开它,但不应该定义它.
为什么这很重要?因为它再次使重用该功能变得容易.控制器中定义的函数不能在另一个控制器中重用,而不限制在HTML中调用控制器的方式.在服务中定义的函数可以在任何您喜欢的地方注入和重用.
但我不需要重用该功能!- 是的你是!也许不是现在,也许从来没有这个特定的功能,但迟早你最终会想要重用一个你确信你永远不需要重用的功能.然后你将不得不重做你已经忘记了一半的代码,这总是需要额外的时间.
最好从一开始就正确地做到这一点,并将所有可用的逻辑转移到服务中.这样,如果您在其他地方(甚至在另一个项目中)需要它们,您可以抓住它并使用它而无需重写它以适合您当前的范围结构.
当然,服务不了解您的范围,因此您不得不使用第一个版本.奖金!并且不要因为将整个范围传递给服务的诱惑,这将永远不会结束:-)
所以这是IMO最好的选择:
app.service('ToDoService', [function(){
this.addToDo = function(params1, ...){
alert(params1);
}
}]);
Run Code Online (Sandbox Code Playgroud)
在控制器内部:
$scope.addToDo = ToDoService.addToDo;
Run Code Online (Sandbox Code Playgroud)
请注意,我写了"一般规则".在某些情况下,在控制器本身而不是服务中定义函数是合理的.一个例子是当函数仅涉及范围特定事物时,例如以某种方式切换控制器中的状态.在没有变得奇怪的情况下,在服务中没有真正的方法可以做到这一点.
但听起来这并非如此.
Treat scope as read only in templates Treat scope as write only in controllers
遵循这个原则,您应该始终使用模板中的参数调用函数表达式.
但是,无论您遵循何种风格,都必须注意priorities指令的执行顺序.在您的示例中,使用ng-model和ng-click保留两个指令的执行顺序不明确.解决方案正在使用ng-change,其中执行顺序是明确的:它将仅在值更改后执行.
| 归档时间: |
|
| 查看次数: |
58612 次 |
| 最近记录: |