AngularJS巩固实践-37-使用Controller as Vm方式
ng从1.2开始引入语法Contorller as Vm
在之前的版本需要在Controller中注入$scope服务才能在视图绑定中使用这些变量。
比如:1
2
3
4
5
6
7
8angular.module('com.ngnice.app').controller('DemoController', function($scope){
$scope.title = 'Angular';
});
// 使用如下:
<div ng-app="com.ngnice.app" ng-controller="DemoController">
hello: {{ title }}
</div>
在controller中需要显示注入$scope, 对controller来说,$scope几乎是必须使用的对象,所以几乎每次都加入这个参数,这显得有些多余和累赘,所以ng引入了新的语法糖:controller as,上述代码可改为:1
2
3
4
5
6
7
8angular.module('com.ngnice.app').controller('DemoController', function(){
this.title = 'Angular';
});
// 使用如下:
<div ng-app="com.ngnice.app" ng-controller="DemoController as demo">
hello: {{ demo.title }}
</div>
此处,controller中没有注入$scope服务,所以controller更像是一个普通的js函数对象,而新的语法在使用时为controller引入了一个别名,方便在ng-controller的DOM区内的视图模板通过别名来访问数据对象。
源码如下:1
2
3
4
5controllerInstance = $controller(controller, locals);
...
if(directive.controllerAs){
locals.$scope[directive.controllerAs] = controllerInstance;
}
ng将controller对象实例以其as为别名放在$scope上,所以视图模板能够访问。
对比controller as语法,更清晰也更好的方法为:1
2
3
4
5angular.module('com.ngnice.app').controller('DemoController', function(){
var vm = this;
vm.title = 'Angular';
return vm;
})
这样做的好处时,避免js中this指针的一些问题。也可以在controller中注入$scope同时声明一个内部变量1
var vm = $scope.vm = {};
原则上在controller中应该避免使用$watch、$emit、$on等$scope提供的特殊的方法。但当一定要使用这些方法时,就需要使用注入$scope的方式。
同时因controller实例将会成为$scope服务的一个属性,所以视图模板上所有的字段都会现在在一个别名引用属性上,这样可以避开js原型链继承对普通值类型的覆盖问题。
然后由于没有注入$scope, controller也更接近普通js对象,所以后期可以利用coffeescript等提供的class语法来实现,看起来更好。
最后多重controller嵌套的情况下,由于每个字段都会用别名,所以能避免嵌套继承的命名冲突问题。
路由中使用controller as语法
一般ng应用都时单页面应用,需要用到ng-route或ui-route来知道controller,他们也支持这种as语法:
以ng-route为例:1
2
3
4
5
6
7angular.module('com.ngnice.app').config(function($routeProvider){
$routeProvider.when('/Book/:bookId', {
templateUrl: 'book.html',
controller: BookController,
controllerAs: 'book'
});
})
指令中也可以使用controller as语法:1
2
3
4
5
6
7
8
9
10
11
12angular.module('com.ngnice.app').controller('DemoController', function(){
var vm = this;
vm.title = 'Angular';
return vm;
}).directive('hello',function(){
return {
restrict: 'EA',
controllerAs: 'vm',
template: '<div>{{vm.title}}</div>',
controller: 'DemoController'
};
});
但上述方式在通过scope:{}声明的变量仍然会自动绑定到$scope而不是vm上,所以需要开启bindToController选项:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16angular.module('com.ngnice.app').controller('DemoController', function(){
var vm = this;
vm.title = 'Angular';
return vm;
}).directive('hello',function(){
return {
restrict: 'EA',
scope: {
name: =
}
controllerAs: 'vm',
bindToController: true,
template: '<div>{{vm.title}}</div>',
controller: 'DemoController'
};
});