在Angular中使用依赖注入(DI)的时候,咱们通常会使用providers
。其实要作一样的事咱们还有另一个选择:viewProviders
。 viewProviders
容许咱们定义只对组件的view可见的provider。下面咱们用例子详细的说明这一点。 假设咱们有一个简单的服务:ide
// myService.service.ts import { Injectable } from '@angular/core'; @Injectable() export class MyService{ testIfGetService(where){ console.log('Got My Service in ' + where); } }
这个服务很简单,只须要打印出在哪里调用了该服务。 而后有一个子组件,是用来投射到父组件里面的(等会将会看到):this
// child.component.ts import { Component } from '@angular/core'; import { MyService } from './myService.service'; @Component({ selector: 'vp-child', template: ` <div>This is child!!!</div> ` }) export class VPChild{ constructor( private service: MyService ){ this.service.testIfGetService('child'); } }
这个组件注入了MyService
服务,调用MyService
的testIfGetService
方法,并传入child
代表这是在child组件调用的。 还有另一个子组件,这个组件是用来放在父组件的模板(template)里面的:google
// viewChild.component.ts import { Component } from '@angular/core'; import { MyService } from './myService.service'; @Component({ selector: 'vp-viewchild', template: ` <div>This is viewChild!!!</div> ` }) export class ViewVPChild{ constructor( private service: MyService ){ this.service.testIfGetService('viewChild'); } }
这里一样注入MyService
服务,调用MyService
服务的testIfGetService
方法,并传入viewChild
。 最后是父组件:code
// parent.component.ts import { Component } from '@angular/core'; import { MyService } from './myService.service'; @Component({ selector: 'vp-parent', template: ` <div>This is parent!!!</div> <ng-content></ng-content> <vp-viewchild></vp-viewchild> `, providers: [MyService] }) export class VPParent{ constructor( private service: MyService ){ this.service.testIfGetService('parent'); } }
在父组件,用providers
注册MyService
,而后调用MyService
的testIfGetService
传入parent
。 而后就像这样使用父组件:component
<vp-parent> <vp-child></vp-child> </vp-parent>
运行程序,控制台打印出告终果: blog
一切就像预期那样!! 而后,咱们用viewProviders
代替providers
注册MyService
,看看会发生什么:console
// parent.component.ts import { Component } from '@angular/core'; import { MyService } from './myService.service'; @Component({ selector: 'vp-parent', template: ` <div>This is parent!!!</div> <ng-content></ng-content> <vp-viewchild></vp-viewchild> `, viewProviders: [MyService] // <--- }) export class VPParent{ constructor( private service: MyService ){ this.service.testIfGetService('parent'); } }
这样修改以后,运行程序,发现报错了: table
若是把contentChild注释掉,就像这样:模板
<vp-parent> <!-- <vp-child></vp-child> --> </vp-parent>
是不会报错的: class
这就说明,在父组件用viewProviders
注册的provider,对contentChildren是不可见的。而使用providers
注册的provider,对viewChildren和contentChildren均可见! 补充说明:组件会逐级向上寻找provider,直到找到为止,不然就会抛出错误。就像这里:
<vp-parent> <vp-child></vp-child> </vp-parent>
vp-child
往上找MyService
的provider,结果在vp-parent
找到了。可是在用viewProviders
的时候,vp-child
往上找,也就是到vp-parent
,结果没找到,而后又去找vp-parent
的父级,仍是没找到(由于在这个例子里,咱们只在vp-parent
注册了MyService
),而后又继续往上找……如此找到边界也没找到,因此抛出了一个错误。若是你不但愿这样,可使用@Host
作出限制,就像这样:
constructor( @Host() private service: MyService ){}
关于@Host()本文不做展开,有兴趣能够自行google。