【CSS-10】
angualr控制器是什么?
小课堂【武汉分院第124期】
分享人:徐恒
目录
1.背景介绍
2.知识剖析
3.常见问题
4.解决方案
5.编码实战
6.扩展思考
7.参考文献
8.更多讨论
一.背景介绍
理解控制器
控制器在AngularJS中的作用是增强视图。
AngularJS中的控制器是一个函数,用来向视图的作用域中添加额外的功能。我们用它来给
作用域对象设置初始状态,并添加自定义行为。
当我们在页面上创建一个新的控制器时,AngularJS会生成并传递一个新的 $scope 给这个控
制器。可以在这个控制器里初始化 $scope 。由于AngularJS会负责处理控制器的实例化过程,我
们只需编写构造函数即可。
下面的例子展示了控制器初始化:
function FirstController($scope) {
$scope.message = "hello";
}
提示:将控制器命名为 [Name]Controller 而不是 [Name]Ctrl 是一个最佳实践。
正如我们看到的那样,AngularJS会在创建作用域时调用控制器方法。
细心的读者会发现,我们是在全局作用域中创建的这个函数。这样做并不合适,因为会污染
全局命名空间。更合理的方式是创建一个模块,然后在模块中创建控制器,如下所示:
var app = angular.module('app', []);
app.controller('FirstController', function($scope) {
$scope.message = "hello";
});
只需创建控制器作用域中的函数,就能创建可以在视图中使用的自定义操作。很幸运,
AngularJS允许我们在视图中像调用普通数据一样调用 $scope 上的函数。
用内置指令 ng-click 可以将按钮、链接等其他任何DOM元素同点击事件进行绑定。 ng-click 指
令将浏览器中的 mouseup 事件,同设置在DOM元素上的事件处理程序绑定在一起(例如,当浏览器
在某个DOM元素上触发了点击事件,函数就会被调用)。和前面的例子类似,绑定看起来是这样的:
The simplest adding machine ever
AddSubtract
Current count: {{ counter }}
按钮和链接都被绑定在了内部 $scope 的一个操作上,当点击任何一个元素时AngularJS都会
调用相应的方法。注意,当设置调用哪个函数时,会同时用括号传递一个参数( add(1) )。
下面给 FirstController 添加一个操作:
var app = angular.module('app',[]);
app.controller('FirstController', function($scope) {
$scope.counter = 0;
$scope.add = function(amount) { $scope.counter += amount; };
$scope.subtract = function(amount) { $scope.counter -= amount; };
});
用这种设置方式我们可以在视图中调用 add() 或 subtract() 方法,这两个方法可以定义在
FirstController 的作用域中,或其父级的 $scope 中。
控制器可以将与一个独立视图相关的业务逻辑封装在一个独立的容器中。尽可能地精简控制
器是很好的做法。作为AngularJS开发者,使用依赖注入来访问服务可以实现这个目的。
AngularJS同其他JavaScript框架最主要的一个区别就是,控制器并不适合用来执行DOM操
作、格式化或数据操作,以及除存储数据模型之外的状态维护操作。它只是视图和 $scope 之间的
桥梁。
AngularJS允许在 $scope 上设置包括对象在内的任何类型的数据,并且在视图中还可以展示
对象的属性。
例如,我们在 MyController 上创建一个 person 对象,这个对象只有 name 这一个属性:
app.controller('MyController', function($scope) {
$scope.person = {
name: 'Ari Lerner'
};
});
在拥有 ng-controller='MyController' 这个属性的元素内部的任何子元素中,都可以访问
person 对象,因为它是定义在 $scope 上的。
例如,可以方便地在视图中引用 person 或 person.name ,效果如图所示。
{{ person }}
and their name:
{{ person.name }}
正如看到的这样, $scope 对象用来从数据模型向视图传递信息。同时,它也可以用来设置事
件监听器,同应用的其他部分进行交互,以及创建与应用相关的特定业务逻辑。
AngularJS通过作用域将视图、控制器和指令(以后介绍)隔离开来,这样就很容易
为功能的具体部分编写测试。
控制器嵌套(作用域包含作用域)
ngularJS应用的任何一个部分,无论它渲染在哪个上下文中,都有父级作用域存在。对于
ng-app 所处的层级来讲,它的父级作用域就是 $rootScope 。
有一个例外:在指令内部创建的作用域被称作孤立作用域。
除了孤立作用域外,所有的作用域都通过原型继承而来,也就是说它们都可以访问父级作用
域。如果熟悉面向对象编程,对这个机制应该不会陌生。
默认情况下,AngularJS在当前作用域中无法找到某个属性时,便会在父级作用域中进行查
找。如果AngularJS找不到对应的属性,会顺着父级作用域一直向上寻找,直到抵达 $rootScope
为止。如果在 $rootScope 中也找不到,程序会继续运行,但视图无法更新。
通过例子来看一下这个行为。
下面是一个拥有三层div结构,也就对应有三层 scope 继承关系的层级结构(不包括 rootScope 的话),demo中的蓝色边框很清晰的展现了 scope 的层级和DOM层级的对应关系。它还展示了“scope 是由 ng-controller 指令创建并由其对应的控制器所管理”这个概念。
Good {{timeOfDay}}, {{name}} !
Good {{timeOfDay}}, {{name}} !
Good {{timeOfDay}}, {{name}},!
var myApp = angular.module('scopeInheritance', []);
myApp.controller('MainCtrl', ['$scope', function($scope){
$scope.timeOfDay = 'morning';
$scope.name = 'Nikki';
}]);
myApp.controller('ChildCtrl', ['$scope', function($scope){
$scope.name = 'Mattie';
}]);
myApp.controller('GrandChildCtrl', ['$scope', function($scope){
$scope.timeOfDay = 'evening';
$scope.name = 'Gingerbreak Baby';
}]);
注意,上面例子中我们在HTML模板中嵌套了三个 ng-controller 指令,这导致我们的视图中有4个 scope:
root scope,所有作用域的“根”
MainCtrl 控制器管理的 scope (简称 MainCtrl scope),拥有 timeOfDay 和 name 两个属性
ChildCtrl 控制器管理的 scope (简称 ChildCtrl scope),继承了 MainCtrl scope 中的 timeOfDay 属性,但重写了它的 name 属性
GrandChildCtrl 控制器管理的 scope (简称 GrandChildCtrl scope),重写了 MainCtrl scope 中的 timeOfDay 属性和 ChildCtrl scope 中的 name 属性
控制器中,方法继承和属性继承的工作方式是一样的,所以,上面例子中的所有属性,我们也可以改写成能够返回字符串值的方法,同样有效。
控制器应该尽可能保持短小精悍,而在控制器中进行DOM操作和数据操作则是一个不好的
实践。
例如,下面这个例子中的控制器包含了过于臃肿的逻辑用于控制视图,并且还操作了DOM。
臃肿的控制器:
angular.module('myApp', [])
.controller('MyController', function($scope) {
$scope.shouldShowLogin = true;
$scope.showLogin = function () {
$scope.shouldShowLogin = !$scope.shouldShowLogin;
};
$scope.clickButton = function() {
$('#btn span').html('Clicked');
};
$scope.onLogin = function(user) {
$http({
method: 'POST',
url: '/login',
data: {
user: user
}
}).success(function(data) {
// user
});
};
});
设计良好的应用会将复杂的逻辑放到指令和服务中。通过使用指令和服务,我们可以将控制
器重构成一个轻量且更易维护的形式:
简洁的控制器:
angular.module('myApp', [])
.controller('MyController', function($scope,UserSrv) {
// 内容可以被指令控制
$scope.onLogin = function(user) {
UserSrv.runLogin(user);
};
});
二.知识剖析
三.常见问题
四.解决方案
五.代码实战
六.拓展思考
七.参考文献
八.更多讨论
鸣谢
感谢大家观看
BY : 徐恒
1.如何在directive中的link函数中调用controller方法?
2.一个名字的控制器能写两次么,以哪个为准?
3.控制器和directive中的controller有什么区别?
4.一个程序中怎么写控制器比较合理?
------------------------------------------------------------------------------------------------------------------------
技能树.IT修真院
“我们相信人人都可以成为一个工程师,现在开始,找个师兄,带你入门,掌控自己学习的节奏,学习的路上不再迷茫”。
这里是技能树.IT修真院,成千上万的师兄在这里找到了自己的学习路线,学习透明化,成长可见化,师兄1对1免费指导。快来与我一起学习吧 !