AngularJS看起来很乱,难以阅读。在控制器中的$ scope访问的一些非常抽象的netherworld中存在一个模型。一旦我有一个100行长的控制器,一个50行长的部分模板,15个指令和凌乱的CSS类行为,它很难保持变量,他们做什么,以及它们在代码中的位置。
我正在查看Todo应用示例:
angular.module('todomvcApp')
.controller('MainCtrl', function ($scope, $timeout, Todo, filterFilter, $location) {
$scope.todos = [];
$scope.newTodo = '';
$scope.editedTodo = null;
$scope.status = $location.search().q || '';
//.............
$scope.$watch('todos', function () {
$scope.remainingCount = filterFilter($scope.todos, { completed: false }).length;
$scope.completedCount = $scope.todos.length - $scope.remainingCount;
$scope.allChecked = !$scope.remainingCount;
}, true);
//............
$scope.editTodo = function (id) {
$scope.editedTodo = $scope.todos[id];
$scope.originalTodo = angular.extend({}, $scope.editedTodo);
};
//............
$scope.revertEditing = function (id) {
$scope.todos[id] = $scope.originalTodo;
$scope.doneEditing(id);
};
});
以下是一些需要初始化的$ scope变量:
$scope.todos
$scope.newTodo
$scope.editedTodo
$scope.status
但是,为什么其他不需要初始化的$ scope变量也未在作者的早期定义?例如
$scope.orginialTodo
这使得代码在部分模板和控制器中都很难读取。是否有一种结构或模式可以帮助清除Angular中的变量组织?
答案 0 :(得分:1)
我个人发现使用_.extend(或angular.extend)来初始化/定义范围属性看起来比每行一次的$ scope.XX = X更清洁,并且有助于文件的可读性。
我也总是在控制器/链接fn的开头初始化变量,即使变量将被异步设置。这允许在使用一个文件时非常快速地查看所有变量,而不会错过稍后初始化的文件。
你拥有的变量越多,就越真实。
_.extend($scope, {
todos : [],
newTodo : '',
editedTodo : null // even if if will be initialized later
});
你的例子或多或少会有以下几点:
angular.module('todomvcApp')
.controller('MainCtrl', function ($scope, $timeout, Todo, filterFilter, $location) {
_.extends($scope, {
todos : [],
newTodo : '',
editedTodo : null,
status : $location.search().q || ''
});
// .............
$scope.$watch('todos', function (todos) {
_.extend($scope, {
remainingCount : filterFilter(todos, { completed: false }).length,
completedCount : todos.length - $scope.remainingCount,
allChecked : $scope.remainingCount
});
}, true);
// ............
$scope.editTodo = function (id) {
$scope.editedTodo = $scope.todos[id];
$scope.originalTodo = angular.extend({}, $scope.editedTodo);
};
// ............
$scope.revertEditing = function (id) {
$scope.todos[id] = $scope.originalTodo;
$scope.doneEditing(id);
};
});
答案 1 :(得分:0)
是的。基本上,避免范围汤。 在构造函数中声明您的属性,并使用' this'来访问它们。 你应该避免建立你的范围对象......
为什么呢?将方法和属性直接放在控制器上,而不是构建范围对象,更适合Google Closure类样式。另外,使用'控制器作为'当多个控制器应用于元素时,显而易见的是您正在访问哪个控制器。因为总有一个'。在绑定中,您不必担心原型继承掩盖原语。
在版本1.2之后,控制器'作为'语法使这更加简化。
这个方法可能会自然产生一个问题,"如何在构造函数之外访问我注入的服务"?...
How should I reference services in my controller functions without using scope?
Syle指南示例
不使用Controller别名
<div ng-controller="hello.mainpage.HomeCtrl"/>
<span ng-class="homeCtrl.myColor">I'm in a color!</span>
<span>{{homeCtrl.add(5, 6)}}</span>
</div>
/**
* Home controller.
*/
hello.mainpage.HomeCtrl = function($scope) {
$scope.homeCtrl = this; // This is a bridge until Angular 1.2 controller-as
this.myColor = 'blue';
};
hello.mainpage.HomeCtrl.prototype.add = function(a, b) {
return a + b;
};
版本1.2之后,使用Controller-as Syntax
<div ng-controller="hello.mainpage.HomeCtrl as homeCtrl"/>
<span ng-class="homeCtrl.myColor">I'm in a color!</span>
<span>{{homeCtrl.add(5, 6)}}</span>
</div>
/**
* Home controller.
*/
hello.mainpage.HomeCtrl = function() {
this.myColor = 'blue';
};
hello.mainpage.HomeCtrl.prototype.add = function(a, b) {
return a + b;
};
最后,尝试使用这些指南重构原始Todo(1.2后指南)
var MainCtrl = function($timeout, Todo, filterFilter, $location){
var that =this;
this.todos = [];
this.newTodo = '';
this.editedTodo = null;
this.originalTodo = null;
this.status = $location.search().q || '';
this.$watch('todos',function(){
that.remainingCount = filterFilter(that.todos, { completed: false }).length;
that.completedCount = that.todos.length - that.remainingCount;
that.allChecked = !that.remainingCount;
});
};
MainCtrl.prototype.editTodo = function (id) {
this.editedTodo = this.todos[id];
this.originalTodo = angular.extend({}, this.editedTodo);
};
MainCtrl.prototype.revertEditing = function(){
this.todos[id] = this.originalTodo;
this.doneEditing(id);
};
MainCtrl.$inject=['$timeout', 'Todo', 'filterFilter', '$location'];