私は、Angular2で(DI)依存性注入がどのように機能するかを理解しようとしています。コンポーネントにサービスやクラスを挿入しようとするたびに、多くの問題や問題に遭遇しました。
さまざまなグーグルの記事から、コンポーネント構成で_providers: []
_を使用する必要があります。または、コンストラクターで@Inject()
を使用するか、bootstrap(app, [service])
に直接注入する必要があります。また、いくつかの記事で_@injectable
_デコレータを配置することを求めています。
たとえば、Httpを注入するには、_import{Http}
_だけを使用してプロバイダーにHttpを配置する必要がありますが、FormBuilderでは、コンストラクターで@Inject()
を使用する必要があります。
何を使用するかについての経験則はありますか?サンプルコードスニペットを提供してください。ありがとうございました :-)
Angular2の依存性注入は、コンポーネントのツリーにリンクされている階層的なインジェクターに依存しています。
これは、異なるレベルでプロバイダーを構成できることを意味します。
他の質問について:
詳細については、次の質問を参照してください。
幅広い質問、TL; DRバージョン
は、装飾されたクラスにTypeScript
があることをdependencies
に伝えるデコレーターであり、このクラスを他のクラスに注入できることを意味するものではありません。
そして、TypeScriptは、imported
依存関係を使用して、構築時に必要なメタデータを装飾されたクラスに挿入する必要があることを理解します。
bootstrap()は、ブートストラップされるときにアプリケーションのルートインジェクターを作成します。プロバイダーのリストを2番目の引数として取り、作成時にインジェクターに直接渡します。
bootstrap Http
のような多くの場所で使用されるサービスを備えたアプリケーション。これは、クラス構成に_providers: [Http]
_を記述する必要がないことも意味します。 。
プロバイダーは、すべてのサービスの引数をInjector
に渡す作業も行います。
bootstrap()
pedでない場合は、サービスをプロバイダーに配置します。そして、いくつかの場所でのみ必要です。
constructor(@Inject(NameService) nameService)
constructor(nameService: NameService)
だけで、TypeScriptが残りを処理します。さらに読む
深く掘り下げたい場合[〜#〜] di [〜#〜]、 この驚くべき記事 =
_Gunter's Answer
__Mark Rajcok's Answer
_ および _Accepted Answer
_
お役に立てれば。 :)
プロバイダーを使用する必要があります:[]
依存性注入がインスタンスを作成できるようにするには、これらのクラス(または他の値)のプロバイダーを登録する必要がありますsomewhere。
プロバイダーを登録する場所によって、作成される値の範囲が決まります。 Angulars DIは階層的です。
ツリーのルートでプロバイダーを登録する場合
> = RC.5
_@NgModule({
providers: [/*providers*/]
...
})
_
または遅延読み込みモジュールの場合
_static forRoot(config: UserServiceConfig): ModuleWithProviders {
return {
ngModule: CoreModule,
providers: [
{provide: UserServiceConfig, useValue: config }
]
};
}
_
<= RC.4
(bootstrap(AppComponent, [Providers})
または@Component(selector: 'app-component', providers: [Providers])
(ルートコンポーネント)
インスタンスを要求するすべてのコンポーネントとサービスは同じインスタンスを取得します。
プロバイダが子コンポーネントの1つに登録されている場合、このコンポーネントの子孫に新しい(異なる)インスタンスが提供されます。
コンポーネントが(コンストラクターパラメーターによって)インスタンスを要求すると、DIはコンポーネントツリーを「上」に見て(リーフからルートに向かって)、見つけた最初のプロバイダーを取得します。このプロバイダーのインスタンスが既に作成されている場合、このインスタンスが使用されます。それ以外の場合は、新しいインスタンスが作成されます。
@Inject()
コンポーネントまたはサービスがDIに値を要求するとき
_constructor(someField:SomeType) {}
_
DIは、SomeType
型でプロバイダーを検索します。 @Inject(SomeType)
が追加された場合
_constructor(@Inject(SomeType) someField:SomeType) {}
_
DIは、@Inject()
に渡されたパラメーターによってプロバイダーを検索します。上記の例では、@Inject()
に渡されるパラメーターはパラメーターの型と同じであるため、@Inject(SomeType)
は冗長です。
ただし、構成設定を挿入するなど、動作をカスタマイズする必要がある場合があります。
_constructor(@Inject('someName') someField:string) {}
_
タイプstring
は、複数の登録がある場合に特定の構成設定を区別するには不十分です。
構成値は次のようなプロバイダーとして登録する必要があります
> = RC.5
_@NgModule({
providers: [{provide: 'someName', useValue: 'abcdefg'})]
...
})
export class AppModule {}
_
<= RC.4
_bootstrap(AppComponent, [provide('someName', {useValue: 'abcdefg'})])
_
そのため、コンストラクタが次のように見える場合、FormBuilder
に対して@Inject()
は必要ありません
_constructor(formBuilder: FormBuilder) {}
_
他の回答で言及されていないものをいくつか追加します。 (私がこれを書いているとき、それはティエリー、ギュンター、およびA_Singhからの答えを意味します)。
Injectable()
を追加してください。サービス自体が何かを挿入する必要がある場合にのみ必要ですが、常に含めることをお勧めします。providers
配列とNgModulesのproviders
配列は、組み込みではないプロバイダーを登録する2つの方法です。 (登録する必要のない組み込みオブジェクトの例は、ElementRef
、ApplicationRef
などです。これらを単純に挿入できます。)providers
配列がある場合、そのコンポーネントはAngularインジェクター。インジェクターは、何かが依存関係(コンストラクターで指定)をインジェクトしたいときに参照されます。インジェクターツリーをコンポーネントツリーよりも予備のツリーと考えるのが好きです。依存関係の要求を満たすことができる最初のインジェクターはそうします。なぜ@Injectable()なのか?
@Injectable()は、インスタンス化のためにインジェクターが使用できるクラスをマークします。一般的に、インジェクターは@Injectable()としてマークされていないクラスをインスタンス化しようとするとエラーを報告します。
たまたま、最初のバージョンのHeroServiceにはパラメーターが挿入されていないため、@ Injectable()を省略できました。しかし、私たちのサービスには依存性が注入されているので、今それが必要です。 AngularはLoggerを注入するためにコンストラクタパラメータメタデータを必要とするため、必要です。
提案:すべてのサービスクラスに@INJECTABLE()を追加するすべてのサービスクラスに@Injectable()を追加することをお勧めします。依存関係がなく、したがって技術的にそれを必要としないものも含めます。その理由は次のとおりです。
将来の証明:後で依存関係を追加するときに@Injectable()を覚えておく必要はありません。
一貫性:すべてのサービスは同じルールに従い、デコレーターが欠落している理由を疑問に思う必要はありません。
インジェクターは、HeroesComponentなどのコンポーネントのインスタンス化も担当します。 HeroesComponentを@Injectable()としてマークしなかったのはなぜですか?
本当に必要な場合は追加できます。 HeroesComponentはすでに@Componentでマークされているため、このデコレータークラス(後で説明する@Directiveや@Pipeなど)はInjectableMetadataのサブタイプであるため、必要ありません。実際、インジェクタによるインスタンス化のターゲットとしてクラスを識別するのは、InjectableMetadataデコレータです。
ソース: https://angular.io/docs/ts/latest/guide/dependency-injection.html