AngularJS依赖注入
文中内容基本上来自《AngularJS权威教程》
一个对象通常有三种方式可以获得对其依赖的控制权:
- 在内部创建依赖
- 通过全局变量进行引用
- 在需要的地方通过参数进行传递
依赖注入是通过第三种方式实现的。依赖注入是一种设计模式,它可以去除对依赖关系的硬编码,从而可以在运行时改变甚至移除依赖关系。
在运行时修改依赖关系的能力对测试来讲是非常理想的,因为它允许我们创建一个隔离的环境,从而在测试环境可以使用模拟的对象取代生产环境中的真实对象。从功能上来看,依赖注入会事先自动查找依赖关系,并将注入目标告知被依赖的资源,这样就可以在目标需要时立即将资源注入进去。在编写依赖于其它对象或库的组件时,我们需要描述组件之间的依赖关系。在运行期,注入器会创建依赖的实例,并负责将它传递给依赖的消费者。
基于以上原因,AngularJS使用$injector(注入器服务)来管理依赖关系的查询和实例化。事实上,$injector负责实例化AngularJS中所有组件,包括应用的模块、指令和控制器等。
在运行时,任何模块启动时$injector都会负责实例化,并将其需要的所有依赖传递进去。
下面是一个简单的示例
angular.module('myApp', [])
.factory('greeter', function() {
return {
greet: function(msg) {alert(msg); }
}
})
.controller('myController',function($scope, greeter) {
$scope.sayHello = function() {
greeter.greet("hello");
};
});
当AngularJS实例化这个模块时,会查找greeter并自然而然的把对它的引用传递进去。
<div ng-app="myApp">
<div ng-controller="myController">
<button ng-click="sayHello()">Hello</button>
</div>
</div>
推断式注入声明
如果没有明确声明,AngularJS会假定参数名称就是依赖的名称。
显式注入声明
可以通过$inject属性来实现显式注入声明的功能,函数对象的$inject属性是一个数组,数组元素的类型是字符串,它们的值就是需要被注入的服务的名称。这种声明方式参数的顺序非常重要。
行内注入声明
AngularJS提供的注入声明的最后一种方式,是可以随时使用的行内注入声明。这种方式其实是一个语法糖,它同前面提到的通过$inject属性进行注入声明的原理是一样的,但允许我们在函数定义时从行内将参数传入。此外它可以避免在定义过程中使用临时变量。
在定义一个AngularJS的对象时,行内声明的方式允许我们直接传入一个参数数组而不是一个函数。数组的元素是字符串,它们代表的是可以被注入到对象中的依赖的名字,最后一个参数就是依赖注入的目标函数对象本身。
例如:
angular.module('myApp')
.controller('myController',['$scope', 'greeter', function($scope, greeter) {}]);
语法糖(Syntactic sugar)
是由英国计算机科学家彼得·约翰·兰达(Peter J. Landin)发明的一个术语,指计算机语言中添加的某种语法,这种语法对语言的功能并没有影响,但是更方便程序员使用。通常来说使用语法糖能够增加程序的可读性,从而减少程序代码出错的机会。