English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية

Angular2 多層注入器の詳細な説明及び例

angular2 の依存注入には多くの内容が含まれていますが、その中の1つのポイントは注入器であり、注入器は非常に難解です。今日は注入器の内容には深入りしませんが、公式ドキュメントを参照してください。今日は注入器のレベルについて説明します。

コンポーネントがサービスを取得するためのコンテナがどのものを選択するかを示します。

簡単に背景を紹介します:ある3のコンポーネントAppComponent キャプションコンポーネント、DetailListコンポーネント(ログリストコンポーネント)、Detailコンポーネント(ログコンポーネント)。

これらの3つのコンポーネントはコンポーネントツリーを形成し、それに対応して、各コンポーネントに独立した注入器があります(時には現れない場合もありますが、これのように考えることができます)。

LoggerServiceというログサービスを追加します。通常の入门方法に従うと、ルートモジュールのprovidersでLoggerServiceを提供します。その結果、アプリケーション全体でLoggerServiceは1つのインスタンスのみになります。これはどういう意味ですか?これは、どのコンポーネントであれ、取得されるのは初めて作成されたLoggerServiceであり、すべてのコンポーネントが同じサービスインスタンスを共有するという意味です。これは時には非常に便利な特性であり、例えば、私たちが使用するグローバル設定などがあります。

グローバルユニークなものは、これが非常に一般的であるため、今回の確認の重点ではありません。今回の説明では、各コンポーネントで個別のLoggerServiceインスタンスを取得する方法について説明します。つまり、各コンポーネントのインスタンスは異なるという意味です。これはng2の依存注入について理解しておくことができます。

どのように実現するかを順番に説明します。

この短文を読むことができる方にわかりやすくするために、基本的なコードを追加しました。

1

/core';
import { BrowserModule } from '@angular',/platform-browser';
/*  */
import { AppComponent } from '.',/app.component';
import { routing } from './app.routing';
import { Title } from '@angular/platform-browser';
import {MessagesModule, GrowlModule, ButtonModule}from 'primeng/primeng';
import {AppDetailComponent}from './app-detail.component';
import {AppDetailListComponent}from './app-detailList.component';
import {LoggerService}from './logger.service';
let allTitle:string="郭志奇";
@NgModule({
 imports: [
 BrowserModule,
 MessagesModule,
 GrowlModule, ButtonModule
 ],
 declarations: [AppComponent, AppDetailComponent, AppDetailListComponent],//現在のモジュールが必要とする指定のコンポーネント情報を宣言
 exports: [],
 providers: [Title],
 bootstrap: [AppComponent]
}
export class AppModule {
 constructor( @Optional() @SkipSelf() parentModule: AppModule) {
 console.log(parentModule);
 if (parentModule) {
  throw new Error(
  'AppModuleはすでにロードされています。AppModuleにのみインポートしてください');
 }
 }
}

2.app.component.ts アプリケーションルートコンポーネント

import { Component, ViewEncapsulation, Host, ViewContainerRef, ReflectiveInjector } from '@angular/core';
import { Title } from '@angular/platform-browser';
import { Message } from 'primeng/primeng';
import {LoggerService}from './logger.service';
@Component({
 selector: 'my-app',
 moduleId: module.id,
 templateUrl: '.',/app.component.html',
 providers: [
  { provide: LoggerService, useClass: LoggerService }
 }
}
export class AppComponent {}}
 subtitle = '(Final)';
 private msgs: Message[];
 constructor(private title: Title, @Host() private logger: LoggerService) {
  this.title.setTitle("AppComponent");
 }
 show(): void {
  this.logger.Debug();
 }
}

注意してください、私たちはルートコンポーネントのprovidersにLoggerServiceを登録しています。

3.app.detailList.ts  ログリストのprovidersにもLoggerServiceが登録されています。

import {Component, Host}from '@angular/core';
import {LoggerService}from './logger.service';
@Component({
 selector: 'my-detailList',
 templateUrl: '.',/app-detailList.component.html',
 moduleId: module.id,
 providers: [
  { provide: LoggerService, useClass: LoggerService }
 }
}
export class AppDetailListComponent {
 constructor(private logger: LoggerService) {
 }
 show(): void {
  this.logger.Debug();
 }
}

 4.app.detail.ts  ログコンポーネントのprovidersにLoggerServiceが登録されていません。

import {Component, Host}from '@angular/core';
import {LoggerService}from './logger.service';
@Component({
 selector: 'detail',
 moduleId: module.id,
 templateUrl: '.',/app-detail.component.html',
 providers: [
  // { provide: LoggerService, useClass: LoggerService }
 }
}
export class AppDetailComponent {
 constructor(private logger: LoggerService) {
 }
 show(): void {
  this.logger.Debug();
 }
}

 今、Chromeを使ってLoggerServiceの階層関係を見てみましょう。

 

依存関係図を確認すると、AppComponentコンポーネントが独自のLoggerServiceを使用し、DetailListコンポーネントも独自のLoggerServiceインスタンスを使用し、Detailコンポーネントが親コンポーネントのDetailListのLoggerServiceインスタンスを使用することがわかります。

現在のところ、私たちの要求に達していないようです。私たちの要求は、各コンポーネントに独自のLoggerServiceインスタンスがあることです。したがって、Detailコンポーネントのprovidersが私たちが忘れたことを仮定すると、原因を特定するのが難しいです。したがって、注入器の検索範囲を制限するために@Host()を追加します。

注入器の上向きの検索方法については、公式ドキュメントを参照してください。

デバッグを便利にするために、@Host().を追加します。

@Host デコレータは、上に検索する行動をホストコンポーネントに制限します

detail.ts 提示detail组件加入@Host()デコレータ

import {Component, Host}from '@angular/core';
import {LoggerService}from './logger.service';
@Component({
 selector: 'detail',
 moduleId: module.id,
 templateUrl: '.',/app-detail.component.html',
 providers: [
  // { provide: LoggerService, useClass: LoggerService }
 }
}
export class AppDetailComponent {
 constructor( @Host() private logger: LoggerService) {
 }
 show(): void {
  this.logger.Debug();
 }
}

LoggerServiceのインスタンスが見つかりませんというエラーメッセージが表示されます。@Host()の役割は、注入器が現在のコンポーネントで停止し、さらに上に検索しないように制限することです。したがって、Providersが見つからないエラーメッセージが表示されます。

providersを追加すると、私たちが欲しい結果になります。

 

多成分がそれぞれのサービスインスタンスを使用する問題を完璧に解決しました。

 まとめ:

1.コンポーネントがサービスを単独で使用する必要がある場合、まずprovidersでそのサービスを単独で登録する必要があります。簡単に理解できます。

2.問題が発生する可能性があることを早めに検出するために、コンポーネントサービスに@Host()デコレータを追加すると、エラーメッセージをできるだけ早く投げることができます。

3.ngを使用2のデバッグツール

4.各コンポーネントの関係を明確にする必要があります。なぜなら、異なるコンポーネント関係がサービスのインスタンスの違いを引き起こすからです。

5.サービスはモジュールレベルで、アプリケーションレベルではありません。

ご読阅ありがとうございます。皆様のサポートに感謝します!

おすすめ