只需创建控制器作用域中的函数,就能创建可以在视图中使用的自定义操作。
比较幸运的事,AngularJS允许我们在视图中像调用普通数据一样调用$scope上的函数。
用内置指令ng-click可以将按钮,链接笔其他任何DOM元素同点击事件进行绑定。ng-click指令
将浏览器中的mouseup事件,同设置在DOM元素上的事件处理程序绑定在一起(例如:当浏览器在某个DOM元素
上触发了点击事件,函数就会被调用)和前面的例子类似,绑定看起来是这样的:
HTML
<div ng-controller="FirstController">
<h4>The simplest adding machine ever</h4>
<button ng-click="add(1)" class="button">Add</button>
<a ng-click="subtract(1)" class="button alert">Subtract</a>
<h4>Current count: {{ counter }}</h4>
</div>
按钮和链接都被绑定在了内部$scope的一个操作上,当点击任何一个元素时AngularJS都会调用相应的方法。
注意,当设置调用某个函数时,会同时用括号传递一个参数(add(1)):
JavaScript
app.controller('FirstController', function($scope) {
$scope.counter = 0;
$scope.add = function(amount) { $scope.counter += amount; };
$scope.subtract = function(amount) { $scope.counter -= amount; };
});
视图可以将一个独立视图相关的业务逻辑封装在一个独立的容器中。尽可能可以定义在FirstCotroller的作用域中,或其父级的$scope中。
开发AngularJS时,使用依赖注入来访问服务可以实现这个目的。
AngularJS同其它的JavaScript框架最主要的区别就是,控制器并不适合用来执行DOM操作
、格式化或数据操作,以及除存储数据模型之外的状态维护操作。它只是视图和$scope之间的桥梁。
AngularJS允许在$scope上设置包括对在内的任何类型的数据,并且在视图中还可以展示对象的属性。
列如,我们在MyController上创建一个person对象。这个对象只有name这一个属性:
在拥有ng-controller='MyController'这个属性的元素内部的任何子元素中,都可以访问person对象,因为它是定义在$scope上的。
HTML
<div ng-app="myApp">
<div ng-controller="MyController">
<h1>{{ person }}</h1>
and their name:
<h2>{{ person.name }}</h2>
</div>
</div>
JavaScript
app.controller('MyController', function($scope) {
$scope.person = {
name: 'M'
};
});
正如看到的这样,$scope对象用来从数据模型向视图传递信息。同事,它也可以用来设置事件监听器,同应用的其他部分进行交互,以及创建与应用相关的特定业务逻辑。
AnagularJS通过作用域将视图、控制器和指令隔离开来,这样就很容易为功能的具体部分编写测试。
控制器嵌套(作用域包含作用域)
AngularJS应用的任何一个部分,无论它渲染哪个上下文中,都有父作用域存在。对于ng-app所处的层级来讲,它的父级作用域就是$rootScope;
有一个例外:在指令内部创建的作用域被称为孤立作用域。
除了孤立作用域外,所有的作用域都通过原型继承而来,也就是说它们都是可以访问父级作用域。
默认情况下,AngularJS在当前作用域中无法找到某个属性时,便会在父级作用域中进行查找。
如果AngualrJS找不到对应的属性,会顺着父级作用域一直向上寻找,知道抵达$rootScope为止。如果在$rootScope中也找不到,程序
会继续运行,但视图无法更新。
创建一个ParentController,其中包含一个user对象,再创建一个ChildController来引用这个对象:
HTML
<div ng-controller="ParentController">
<div ng-controller="ChildController">
<a ng-click="sayHello()">Say hello</a>
</div>
{{ person }}
</div>
如果我们将ChildController置于ParentController内部,那ChildController的$scope对象的父级作用域就是ParentController的
$scope对象。根据原型继承的机制,我们可以在子作用域中访问ParentController的$scope对象。
JavaScript
app.controller('ParentController', function($scope) {
$scope.person = {greeted: false};
});
app.controller('ChildController', function($scope) {
$scope.sayHello = function() {
$scope.person.name = 'Ari Lerner';
};
});
控制器应该尽可能保持短小精悍,而在控制器中进行DOM操作和数据操作则是一个不好的实践。如下:
JavaScript
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
});
};
});
良好的应用会将复杂的逻辑放到指令和服务器中,通过使用指令和服务,我们可以将控制器重构成一个轻量且更容易维护的形式:
简洁的控制器:
JavaScript
angular.module('myApp', [])
.controller('MyController', function($scope,UserSrv) {
// 内容可以被指令控制
$scope.onLogin = function(user) {
UserSrv.runLogin(user);
};
});