依赖声明
INJECTOR如何知道需要给组件提供那些依赖?
程序的开发人员需要明确的声明依赖以便injector
决定如何解决依赖关系。在Angular中,有三种方式可以声明一个组件所依赖的服务:
- 隐式的从函数参数名中推断
- 使用
$inject
属性声明 - 使用数组声明
隐式依赖
最简单获取依赖的方式就是假定函数的参数名就是依赖的名字:
function MyController($scope, greeter) {
// ...
}
给定一个函数,injector
可以通过检查它的参数名来推断出那些服务需要被注入。在上边的例子中,$scope
和greeter
就是需要被注入给MyController的两个服务的名字。
虽然这种方式简单易懂,但它并不适用于使用了JavaScript压缩工具/混淆工具的场景,因为那些工具会将函数的参数名重命名。这使得这种方式只适用于原型开发或是演示程序。
$inject属性声明
为了在允许压缩工具重命名函数参数的前提下还能注入正确的服务,函数需要使用$inject
属性来声明依赖。$inject
是一个包含被注入服务名字的数组。
var MyController = function(renamed$scope, renamedGreeter) {
...
}
MyController['$inject'] = ['$scope', 'greeter'];
在这方式中,$inject
数组中服务的顺序需要与函数参数名中服务的顺序保持一致。以上边的示例代码为例,$scope
服务会被注入到renamed$scope
中,greeter
会被注入到renamedGreeter
中。这里的顺序一定要保持对应。
由于这种方式将声明信息作为属性赋给一个函数,它比较适合定义Controller。
数组声明
使用$inject
属性的方式声明依赖在定义directives或services的时候并不是太方便,因为这些组件是通过factory方法定义的。
比如:
someModule.factory('greeter', function($window) {
// ...
});
会导致代码膨胀为以下的形式(需要额外定义一个临时变量):
var greeterFactory = function(renamed$window) {
// ...
};
greeterFactory.$inject = ['$window'];
someModule.factory('greeter', greeterFactory);
为了避免这种情况,第三种声明方式允许你以如下方式声明:
someModule.factory('greeter', ['$window', function(renamed$window) {
// ...
}]);
在这里,我们没有简单的把一个factory作为第二个参数,取而代之的是一个包含一系列服务名的字符串以及一个函数的数组。
以上三种方式可以互换,且可以在Angular系统中任何支持依赖注入的地方使用。