Angular 2 (ベータ版) で 1 つのサービスを別のサービスに挿入する最適な方法は何ですか? 質問する

Angular 2 (ベータ版) で 1 つのサービスを別のサービスに挿入する最適な方法は何ですか? 質問する

サービスをコンポーネントに挿入する方法はわかっていますが (@Component 経由)、DI を使用してコンポーネントの外部にサービスを渡すにはどうすればよいですか?

言い換えれば、私はこれをしたくないのです:

export class MyFirstSvc {

}

export class MySecondSvc {
    constructor() {
        this.helpfulService = new MyFirstSvc();
    }
}

export class MyThirdSvc {
    constructor() {
        this.helpfulService = new MyFirstSvc();
    }
}

ベストアンサー1

はい、まず最初に、@Injectable注入したい各サービスにデコレータを追加します。実際、Injectable名前は少しわかりにくいです。クラスが「注入可能」になるという意味ではなく、コンストラクタ パラメータを注入できるようにデコレートするという意味です。詳細については、この github の問題を参照してください。Angular 4.0 の新機能

インジェクション メカニズムについての私の理解は次のとおりです。@Injectableクラスのデコレータを設定すると、Angular は現在の実行チェーンのインジェクタ内の対応するタイプのインスタンスを作成または取得しようとします。実際、Angular2 アプリケーションには 1 つのインジェクタだけではなく、インジェクタのツリーがあります。インジェクタは、アプリケーション全体とコンポーネントに暗黙的に関連付けられています。このレベルの重要な機能の 1 つは、インジェクタが階層的にリンクされていることです。このインジェクタのツリーは、コンポーネントのツリーをマップします。「サービス」にはインジェクタは定義されていません。

サンプルを見てみましょう。次のようなアプリケーションがあります。

  • コンポーネント:関数AppComponent内でAngular2アプリケーションを作成するときに提供されるアプリケーションのメインコンポーネントbootstrap

    @Component({
      selector: 'my-app', 
        template: `
          <child></child>
        `,
        (...)
        directives: [ ChildComponent ]
    })
    export class AppComponent {
    }
    
  • コンポーネント:コンポーネントChildComponent内で使用されるサブコンポーネントAppComponent

    @Component({
        selector: 'child', 
        template: `
          {{data | json}}<br/>
          <a href="#" (click)="getData()">Get data</a>
        `,
        (...)
    })
    export class ChildComponent {
      constructor(service1:Service1) {
        this.service1 = service1;
      }
    
      getData() {
        this.data = this.service1.getData();
          return false; 
      }
    }
    
  • 2つのサービス、Service1およびService2:は、およびによってService1使用されますChildComponentService2Service1

    @Injectable()
    export class Service1 {
      constructor(service2:Service2) {
        this.service2 = service2;
      }
    
      getData() {
        return this.service2.getData();
      }
    }
    

    @Injectable()
    export class Service2 {
    
      getData() {
        return [
          { message: 'message1' },
          { message: 'message2' }
        ];
      }
    }
    

これらすべての要素とその関係の概要は次のとおりです。

Application
     |
AppComponent
     |
ChildComponent
  getData()     --- Service1 --- Service2

このようなアプリケーションでは、3 つのインジェクターがあります。

  • bootstrap関数の2番目のパラメータを使用して設定できるアプリケーションインジェクタ
  • AppComponentこのコンポーネントの属性を使用して構成できるインジェクター。providersアプリケーション インジェクターで定義された要素を「参照」できます。つまり、このプロバイダーでプロバイダーが見つからない場合は、この親インジェクターで自動的に検索されます。後者で見つからない場合は、「プロバイダーが見つかりません」というエラーがスローされます。
  • ChildComponent1と同じルールに従うインジェクター。AppComponentコンポーネントに対して実行されるインジェクション チェーンに含まれる要素をインジェクトするには、最初にこのインジェクターでプロバイダーが検索され、次に 1 でAppComponent、最後にアプリケーション 1 でプロバイダーが検索されます。

つまり、 をコンストラクターService1に挿入しようとするとChildComponent、Angular2 はインジェクターを調べChildComponent、次に を調べAppComponent、最後にアプリケーションを調べます。

Service2を に注入する必要があるため、インジェクタ1 とアプリケーション 1 というService1同じ解決処理が実行されます。ChildComponentAppComponent

つまり、コンポーネントの 属性とアプリケーション インジェクターの関数の2 番目のパラメータを使用して、必要に応じて各レベルでService1との両方を指定できます。Service2providersbootstrap

これにより、要素セットの依存関係のインスタンスを共有できるようになります。

  • アプリケーション レベルでプロバイダーを定義すると、対応する作成されたインスタンスがアプリケーション全体 (すべてのコンポーネント、すべてのサービスなど) で共有されます。
  • コンポーネント レベルでプロバイダーを定義すると、インスタンスはコンポーネント自体、そのサブコンポーネント、および依存関係チェーンに関係するすべての「サービス」によって共有されます。

非常に強力で、必要に応じて自由に整理できます。

対応する plunkr はこちらなので、試してみてください:https://plnkr.co/edit/PsySVcX6OKtD3A9TuAEw?p=preview

Angular2 ドキュメントのこのリンクが役に立つかもしれません:https://angular.io/docs/ts/latest/guide/hierarchical-dependency-injection.html

お役に立てれば幸いです(長い回答で申し訳ありません)。Thierry

おすすめ記事