Page 129 - AngularJS权威教程
P. 129
13.1 推断式注入声明 109
angular.module('myApp', []) 1
.factory('greeter', function() {
return {
greet: function(msg) {alert(msg);}
} 2
})
.controller('MyController',
function($scope, greeter) { 3
$scope.sayHello = function() {
greeter.greet("Hello!");
};
}); 4
当AngularJS实例化这个模块时,会查找greeter并自然而然地把对它的引用传递进去:
5
<div ng-app="myApp">
<div ng-controller="MyController">
<button ng-click="sayHello()">Hello</button>
</div> 6
</div>
而在内部,AngularJS的处理过程是下面这样的: 7
// 使用注入器加载应用
var injector = angular.injector(['ng', 'myApp']);
// 通过注入器加载$controller服务:var $controller = injector.get('$controller'); 8
var scope = injector.get('$rootScope').$new();
// 加载控制器并传入一个作用域,同AngularJS在运行时做的一样
var MyController = $controller('MyController', {$scope: scope}) 9
上面的代码中并没有说明是如何找到greeter的,但是它的确能正常工作,因为$injector
会负责为我们查找并加载它。 10
AngularJS通过annotate函数,在实例化时从传入的函数中把参数列表提取出来。在Chrome
的开发者工具中输入下面的代码可以查看这个函数: 11
> injector.annotate(function($q, greeter) {})
["$q", "greeter"]
12
在任何一个AngularJS的应用中,都有$injector在进行工作,无论我们知道与否。当编写
控制器时,如果没有使用[]标记或进行显式的声明,$injector就会尝试通过参数名推断依赖 13
关系。
14
13.1 推断式注入声明
如果没有明确的声明,AngularJS会假定参数名称就是依赖的名称。因此,它会在内部调用 15
函数对象的toString()方法,分析并提取出函数参数列表,然后通过$injector将这些参数注入
进对象实例。注入的过程如下: 16
injector.invoke(function($http, greeter) {});
请注意,这个过程只适用于未经过压缩和混淆的代码,因为AngularJS需要原始未经压缩的 17
参数列表来进行解析。
有了这个根据参数名称进行推断的过程,参数顺序就没有什么重要的意义了,因为AngularJS 18