Angular 4依存注入チュートリアルの6 Injectable装飾器


目次
  • Angular 4依存注入チュートリアルの1つ依存注入概要
  • Angular 4依存注入チュートリアルの2コンポーネントサービス注入
  • Angular 4依存注入チュートリアルの3 ClassProviderの使用
  • Angular 4依存注入チュートリアルの4 FactoryProviderの使用
  • Angular 4依存注入チュートリアルの5 FactoryProvider構成依存オブジェクト
  • Angular 4依存注入チュートリアルの6 Injectableアクセサリ
  • Angular 4依存注入チュートリアルの7 ValueProviderの使用
  • Angular 4依存注入チュートリアルの8 InjectTokenの使用
  • 読書の心得
    このチュートリアルの開発環境と開発言語:
  • Angular 4 +
  • Angular CLI
  • TypeScript

  • 基礎知識
    アクセサリーは何ですか.
  • 式が実行されると、関数
  • が返される.
  • 関数のパラメータはtarge、name、descriptor
  • です.
  • この関数を実行すると、targetオブジェクト
  • を構成するためにdescriptorオブジェクトに戻る可能性があります.
    装飾器の分類
  • 類装飾器(Class decorators)
  • 属性装飾器(Property decorators)
  • 方法装飾器(Method decorators)
  • パラメータ装飾器(Parameter decorators)
  • TypeScript類装飾器
    クラスアクセラレータ宣言:
    declare type ClassDecorator = (target: TFunction) =>    
      TFunction | void

    類装飾器はその名の通り、類を装飾するために使われています.パラメータを受信します.
  • target:Tsuncion-飾られたクラス
  • 一目見た後、気分が悪くなったのではないでしょうか.大丈夫です.すぐに例を挙げましょう.
    function Greeter(target: Function): void {
      target.prototype.greet = function (): void {
        console.log('Hello!');
      }
    }
    
    @Greeter
    class Greeting {
      constructor() { //      }
    }
    
    let myGreeting = new Greeting();
    myGreeting.greet(); // console output: 'Hello!';

    上記の例では、Greeterクラスの装飾器を定義するとともに、@Greeter構文を使用して装飾器を使用します.
    Injectable類装飾器使用
    import { Injectable } from '@angular/core';
    
    @Injectable()
    class HeroService {}

    Injectable装飾器Injectableアクセサリを紹介する前に、HeroComponentコンポーネントを振り返ってみましょう.
    @Component({
      selector: 'app-hero',
      template: `
        
    • ID: {{hero.id}} - Name: {{hero.name}}
    ` }) export class HeroComponent implements OnInit { heros: Array; constructor(private heroService: HeroService, private loggerService: LoggerService) { } ngOnInit() { this.loggerService.log('Fetching heros...'); this.heros = this.heroService.getHeros(); } }
    HeroComponentコンポーネントのngOnInitライフサイクルフックでは、ヒーロー情報を取得する前に、対応するデバッグ情報を出力します.実際には、各アプリケーションのコンポーネントにlog文を追加することを避けるために、log文をgetHeros()メソッド内に配置することができます.
    更新前のHeroServiceサービス
    export class HeroService {
        heros: Array = [
            { id: 11, name: 'Mr. Nice' },
            { id: 12, name: 'Narco' },
            { id: 13, name: 'Bombasto' },
            { id: 14, name: 'Celeritas' },
            { id: 15, name: 'Magneta' },
            { id: 16, name: 'RubberMan' },
            { id: 17, name: 'Dynama' },
            { id: 18, name: 'Dr IQ' },
            { id: 19, name: 'Magma' },
            { id: 20, name: 'Tornado' }
        ];
    
        getHeros() {
            return this.heros;
        }
    }

    更新後のHeroServiceサービス
    import { LoggerService } from './logger.service';
    
    export class HeroService {
        constructor(private loggerService: LoggerService) { }
    
        heros: Array = [
            { id: 11, name: 'Mr. Nice' },
            { id: 12, name: 'Narco' },
            { id: 13, name: 'Bombasto' },
            { id: 14, name: 'Celeritas' },
            { id: 15, name: 'Magneta' }
        ];
    
        getHeros() {
            this.loggerService.log('Fetching heros...');
            return this.heros;
        }
    }

    上記のコードが実行されると、次の異常情報が放出されます.
    Uncaught Error: Can't resolve all parameters for HeroService: (?).

    上記の異常情報は、HeroServiceのすべてのパラメータを解析できないことを示しているが、HeroServiceサービスの構造関数は以下の通りである.
    export class HeroService {
       constructor(private loggerService: LoggerService) { }
    }

    このコンストラクション関数の入力パラメータはloggerServiceであり、そのタイプはLoggerServiceである.研究を続ける前に、HeroServiceが最終的に生成したES5コードを見てみましょう.
    var HeroService = (function() {
       function HeroService(loggerService) {
         this.loggerService = loggerService;
         this.heros = [{...}, ...];
       }
       HeroService.prototype.getHeros = function() {
         this.loggerService.log('Fetching heros...');
         return this.heros;
       };
       return HeroService;
    }());

    生成されたES5コードのうち,HeroServiceコンストラクタには何のタイプの情報も含まれていないため,Angular Injector(インジェクタ)は正常に動作しないことが分かった.では、HeroServiceクラス構造関数のパラメータのタイプ情報をどのように保存しますか?答えを思いついたと思います.もちろんInjectableの装飾器を使っていますよ.次にHeroServiceを更新します.
    import { Injectable } from '@angular/core';
    import { LoggerService } from './logger.service';
    
    @Injectable()
    export class HeroService {
      // ...
    }

    上のコードを更新し、保存に成功したら、http://localhost:4200/ページで、おなじみの「姿」が表示されます.
    ID: 11 - Name: Mr. Nice
    ID: 12 - Name: Narco
    ID: 13 - Name: Bombasto
    ID: 14 - Name: Celeritas
    ID: 15 - Name: Magneta
    HeroServiceクラスで生成されたES5コードを見てみましょう.
    var HeroService = (function() {
         function HeroService(loggerService) {
           this.loggerService = loggerService;
           this.heros = [{...}, ...];
         }
         HeroService.prototype.getHeros = function() {
           this.loggerService.log('Fetching heros...');
           return this.heros;
         };
         return HeroService;
    }());
    HeroService = __decorate([__webpack_require__.i(
      __WEBPACK_IMPORTED_MODULE_0__angular_core__["c"/* Injectable */
    ])(), __metadata("design:paramtypes", ...)], HeroService);

    __decorate関数
    var __decorate = (this && this.__decorate) || function(decorators, target, key, desc) {...};

    __metadata関数
    var __metadata = (this && this.__metadata) || function(k, v) {
      if (typeof Reflect === "object" && typeof Reflect.metadata === "function")
        return Reflect.metadata(k, v);
    };
    Injectableデコレーションを使用していないHeroServiceサービスによって生成されたES5コードよりもHeroService = __decorate(...)コードが多いことが分かった.簡単に説明しますが、Injectableアクセラレータでは、コンパイル時にHeroServiceサービスコンストラクタのパラメータのタイプ情報をReflect APIでwindow['__core-js_shared__']オブジェクトの内部属性に保存します.InjectorHeroServiceオブジェクトを作成すると、Reflect APIを介して、以前に保存されていたコンストラクタ内のパラメータのタイプ情報が読み込まれ、インスタンス化動作が正しく完了する.興味のある読者は、Angular 4を見ることができます.x修仙の道の中のDecorator( )章の関連文章.
    話があるんだ
    @Injectable()は必須ですか?
    作成されたサービスが他のオブジェクトに依存しない場合は、Injectable種類のアクセサリーを使用する必要はありません.しかし、サービスがコンストラクション関数に依存オブジェクトを注入する必要がある場合、Injectable装飾器を使用する必要がある.ただし、依存オブジェクトがあるかどうかにかかわらず、サービス作成時にInjectable種類の装飾器を使用することが推奨されます.