什么是依赖注入
依赖注入是Angular中的一大亮点。先假设一个场景:当一个方法marry(),它的参数是一个类product的实例化对象。也就是
var product=new Product();marry(product);复制代码
一般的操作就是上面这种情况,但是这种情况出现的问题是这会导致组件内部依赖这个Product对象,一个组件是否是一个好的组件,其中一个评价标准是松耦合,重用性高。但是上面这种情况就不行了。
因此,依赖注入就是解决上面这种问题。依赖注入的时候不需要再组件内部new一个对象,只需要声明需要的对象名,实例化部分由组件外部实现,并且外部注入什么,组件就要使用什么。这样组件就不会依赖于某个对象,并且重用性也高。
与依赖注入一并相提的控制反转,这两个是一体两面。控制反转的核心的是为了实现将控制权由组件内部转移到组件外部,这种模式框架就叫做IOC容器。Angular就是一个IOC容器,而控制反转聚焦在目的,而依赖注入聚焦在实现手段,也就是说依赖注入是控制反转的具体实现。
具体实现
依赖注入的操作涉及到两个器:注入器和提供器。
注入器:每个组件斗殴一个注入器实例,负责注入组件需要的对象。但是在Angular中不需要主动调用注入器方法,Angular会自动通过组件的构造函数(constructor)将组件需要的对象注入到组件中。
constructor(private productServeice: ProductService)复制代码
在构造函数中声明要注入的对象的token即可
提供器:提供器一般是通过在模块的@ngModel中的providers中声明,即在providers:[{provide:xxx,useClass:xxx}]
对于提供器还有另外一种作用域,就是在组件中声明,在组件的@Component装饰器中声明providers:[]具体也是如在模块中一样。
至于两者的选择顺序,也就是就近原则吧。
提供器 的另外两种情况
提供器还有一种模式是比较常用到的----工厂提供器(当需要根据某个条件来决定具体实例化哪个对象或者需要在实例化对象中提供参数)
eg
providers:[{ provide:xxx,useFactory:()=>{ }}]复制代码
当useFactory中的匿名函数需要用到外部已经提供的某个方法时,可在该provide中添加一个deps数组属性,在该数组中注入该方法
eg:
providers:[{ provide:xxx,useFactory:(logger:loggerService)=>{ },deps:[loggerService]},loggerService]复制代码
当在useFactory内部需要一个参数,则可以在providers中添加一个token,再在deps中注入即可使用
eg:
providers:[{ provide:xxx,useFactory:(logger:loggerService,param)=>{ 复制代码
},deps:[loggerService,param]复制代码
},loggerService,{provide:'param',useValue:false}]复制代码
在注入的token中,其token名应该是一个字符串,其useValue是其值,也可以是一对象。
服务与服务间互相注入
上面讲到的都是将服务注入到组件中去,但是现实中也存在着将服务注入到服务中去。具体的操作是:
必须要声明一个@Injectable()装饰器-----只有声明了这个装饰器的服务类,才能注入其他服务类。然后后续的操作如将服务注入组件中一样,也需要提供器和注入器。
有可能会问为什么奖服务注入组件时不需要@Injectable()装饰器,其实是组建中有了@Component()装饰器,这个装饰器是@Injectable()的一个子类,故已经声明了@Injectable这个装饰器,不需要再声明