关于AngularJS中的DI
在开始说AngularJS的Service之前,我们先来简单讲讲DI(Dependency Injection,通常中文称之为“依赖注入”)。
DI是一种软件设计模式,主要为了解决组件获取它的依赖组件的问题。DI的概念渗透在AngularJS的各个地方,AngularJS使用一个专门的子系统($injector)进行DI管理,这个过程包括了创建组件、解析、获取它的依赖组件,并将这些依赖组件回传给请求组件。
我们其实已经在不知不觉中使用DI了(比如在AngularJS自定义Directive中的出现过):
app.directive('myCurrentTime', ['$interval', 'dateFilter', function ($interval, dateFilter) {
}
上述代码片段在添加Controller时,其中$interval就是Controller中依赖注入Service的推荐方法。由于$injector的存在,对于我们只需将所需服务的名称传入我们的模块即可,底层的工作都将由$injector包办。
$injector的原理如下图:
AngularJS中使用DI添加Service的三种方法:
方式1(内联注解,推荐使用):
app.controller('myController', ['$scope', 'dateFilter', function ($scope, dateFilter) { }]);
方式2($inject注解):
1 var MyController = function($scope, dateFilter) {2 //...
3 }4 MyController.$inject = ['$scope', 'dateFilter'];5 someModule.controller('MyController', MyController);
方式3(隐式注解,不推荐使用):
app.controller('myController', function ($scope, dateFilter) { });
推荐使用方式1的理由是:
写法上比方法2更简单明了
比方法3更可靠(由于Javascript可以被压缩,AngularJS又是通过解析服务名称找到对应Service的,因此Javascript压缩之后AngularJS将无法找到指定的Service,但字符串不会被压缩,因此单独以字符串指定Service的名称可以避免这个问题)
使用方式1或方式2的注意点:
由于上述第二点原因,AngularJS在编译Html时,由$injector将数组中Service的名称与方法体中的Service进行一一映射。这种映射关系必须遵守由AngularJS的约定:
数组中Service名称的个数必须与方法体中Service名称的个数一致
数组中Service的顺序必须与方法体中Serivce的顺序一致
如果为了编码规范需要强制使用显式DI(也就是方式1或者方式2),可使用ng-strict-di属性,这样AngularJS在遇到隐式DI(也就是方式3)时将会报错。
示例1:
1
2
3
4
5
6 (function() {7 varapp=angular.module('diTest', []);8
9 app.controller('myController1', ['$scope',function($scope) {10 }]);11
12 //方式1 隐式DI,在指定了ng-strict-di后,将会报错
13 //app.controller('myController1', function ($scope) {
14 //});
15
16
17
18 varmyController2= function($scope) {19 };20 myController2.$inject=['$scope'];21 app.controller('myController2', myController2);22
23 //方式2 隐式DI,在指定了ng-strict-di后,将会报错
24 //var myController2 = function ($scope) {
25 //};
26 //app.controller('myController2', myController2);
27 })();28
29
30
31
32