依赖注入是一种软件设计模式,他允许你移除软件组件的硬编码方式,替代的是通过依赖注入制造低耦合的组件不论在编译阶段还是在运行阶段。硬编码就是在程序中将代码写死,低耦合就是尽量让每个模块独立,相关的处理尽量在单个模块中完成。
Angular1有一个内在的注入机制,他可以把你的App分成许多个可重复使用的组件,当需要的时候通过依赖注入把这些自减注入进你的App中去。在需要的地方进行参数传递,这种方法不仅对测试很有用,而且还不会污染全局变量,是很好的设计模式。
Angular1依赖注入的方法
- 通过函数的参数进行推断式注入声明
如果没有明确的声明,Angular1会假定名称就是依赖的名称。因此,它会在内部调用函数对象的toString()方法,分析并提取函数的参数列表,然后通过$injector将这些参数再注入进对象实例。下面是代码示例:
1234567891011function myController($scope,$timeout){var updateTime = function(){$scope.clock = {time: new Date()};$timeout(function(){$scope.clock.time = new Date();updateTime();},1000)}}
|
|
创建了一个可以自动更新时间的应用,看看是如何进行依赖注入的。通过设置参数$scope和$timeout,angular1会在内部调用函数的toString()方法,分析并提取函数的参数列表,然后通过$injector将这些参数注入到对象的实例。
注意:
- 此方法只适合未经压缩混淆的代码,因为angular1需要解析未经压缩混淆的参数列表。
- 显式的注入声明
显式的明确定义一个函数在被调用时需要用到的依赖关系,通过这种方法声明依赖,即使在源代码被压缩,参数名称发生改变的情况下依然可以工作。代码示例:
123456789101112var mycontrollerFactory = function mycontroller($scope,$timeout){var updateTime = function () {$scope.clock = {time: new Date()};$timeout(function () {$scope.clock.time = new Date();updateTime();}, 1000);}updateTime();}
|
|
显式的将我们需要的依赖注入到函数中,所以在函数中参数也可以分别换成其他字段。
|
|
注意:
- 对于这种声明方式,参数的顺序是十分重要的,因为$inject数组元素的顺序必须和注入的参数顺序一一对应。
- 行内注入声明
angular1提供的行内注入方法实际上是一种语法糖,它与前面的提到的通过$inject属性进行声明的原理是一样的,但是允许我们在函数定义的时候从行内将参数传入,这种方法方便简洁,而且避免了在定义的过程中使用临时变量。
12345678910111213angular.module('app',[]).controller('mycontroller',['$scope','$timeout',function($scope,$timeout){var updateTime = function () {$scope.clock = {time: new Date()};$timeout(function () {$scope.clock.time = new Date();updateTime();}, 1000);}updateTime();}])
注意:
- 行内声明的方式允许我们直接传入一个参数数组,而不是一个函数,数组的元素是字符串,他们代表的是可以被注入到对象中的依赖名字,最后一个参数就是依赖注入的目标函数对象本身。
下面来对比一下ng1与ng2的依赖注入的区别,以login组件为例
先来看一下angular2的架构图

Angular1
Angular2
在这里直接把login组件绑定在login service上的,很难进行独立测试,也降低了它复用的可能性
with DI
在构造函数里面注射一个LoginService的实例,而不是直接创建
Angular1
我们还需要告诉框架应该创建这个service的实例
|
|
Angular2
同样,在构造函数里面注射一个LoginSerivce的实例
|
|
- 不同于ng1,我们需要将这个service添加到providers列表里面来实现123456@NgModule({bootstrap:[Login],providers:[LoginService],declarations:[Login]})class AppModule{}
如果注入到它的根模块,则整个应用都可以调用,也可以注入到使用它的组件元数据里面,只需在装饰器加上一个providers配置项,这样注入的服务只对自己和后代可用
|
|
注意: