LoginSignup
5
2

More than 5 years have passed since last update.

【Angular.io】 Architectureまとめ

Last updated at Posted at 2017-07-01

Angular.ioにあるArchitectureについて簡単にまとめました。

モジュール

ルートモジュール

アプリケーションのrootととなるモジュール。アプリケーションをbootstrapする際に必要なモジュールたちをここで一括で読み込む。

フィーチャーモジュール

Root Moduleに読み込まれるモジュールたち。

NgModule

ディレクティブやサービスなどをひとまとまりにしたモジュールを宣言するためのAPI。

import { NgModule }      from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
@NgModule({
  imports:      [ BrowserModule ],
  providers:    [ Logger ],
  declarations: [ AppComponent ],
  exports:      [ AppComponent ],
  bootstrap:    [ AppComponent ]
})
export class AppModule { }
  • declarations
    モジュール内で宣言されているコンポーネント、ディレクティブ、パイプを登録する。一度登録されればそのモジュール内ならどこでも使えるようになる。

  • providers
    アプリケーション / モジュール全体で使用するサービスを登録する。ルートモジュールにproviderを登録する場合は、 同じproviderのインスタンスをアプリケーション全体で共有することが可能だが、コンポーネントのproviderとして登録した場合は、 コンポーネントが作成される度に新しいproviderのインスタンスが作成される。

  • imports
    自分のモジュールに別のモジュールを読み込むことができる。importsから読み込まれたモジュールからはexportsで指定されたものと、providersに登録されたものが読み込まれる。

  • exports
    exportsプロパティにはコンポーネント、ディレクティブとパイプを指定することができる。

  • bootstrap
    アプリケーションのエントリポイントとなるコンポーネントを指定する。

コンポーネント

ビューをコントロールするためのクラスやHTML、CSS、タグを定義する。

@Component({ // メタデータ
  selector: 'my-app’, // ビューで使用するタグ名
  template: '<h1>My First Angular 2 App</h1>' // HTMLテンプレート,
  styleUrls: ['style.css’] // CSSファイル
})
export class AppComponent { } // コンポーネントクラス

テンプレート

コンポーネントで使用するビューファイル

<h2>Hero List</h2>

<p><i>Pick a hero from the list</i></p>
<ul>
  <li *ngFor="let hero of heroes" (click)="selectHero(hero)">
    {{hero.name}}
  </li>
</ul>

<hero-detail *ngIf="selectedHero" [hero]="selectedHero"></hero-detail>

メタデータ

コンポーネント内で使用するメタデータを定義する。以下が主なメタデータ。

  • selector
    HTMLでコンポーネントのインスタンスを埋め込むためのタグ名。

  • templateUrl
    HTMLファイルの指定。

  • providers
    コンポーネント内で使用するサービスを定義。

データバインティング

AngularはDOMとモデル間のデータバインティングを自動的に行ってくれる。

<li>{{hero.name}}</li>
<hero-detail [hero]="selectedHero"></hero-detail>
<li (click)="selectHero(hero)"></li>
  • [hero]="selectedHero"
    親コンポーネントの selectedHero プロパティを 子供コンポーネント(HeroDetailComponent) に hero をプロパティとしてバインディングさせている。

  • (click)="selectHero(hero)”
    クリックされた時に selectedHero を呼び出す。

  • 双方向データバインティング (モデルからビューへ、ビューからモデルへ)
    […] がインプットプロパティ、(…)がアウトプットプロパティを意味している。双方向データバインディングをするには ngModel を使うと簡単にできる。

<input [(ngModel)]=“hero.name”>

Directives

ディレクティブを使用することによって動的にDOMを変更することができる。コンポーネントもディレクティブの一種で、違いはテンプレートを含んでいるかいないか。

  • Structural Directive (構造化ディレクティブ)
    DOMを削除したり、追加したりしてDOMのレイアウトを変更するもの。NgForNgIf など。

  • Attribute Directive (要素ディレクティブ)
    HTML要素に変更を加えるディレクティブ。NgClassNgStyleNgModelなど。

<li *ngFor="let hero of heroes"></li>
<hero-detail *ngIf="selectedHero"></hero-detail>

サービス

シングルトンでコンポーネントやデータの状態を管理するために使われるクラス。複数のコンポーネントから呼び出されたりする。XHRのデータ取得や、バリデーションなどの複雑な処理はコンポーネントではなくサービスで行うのが一般的。コンポーネントの責務はビューとのバインディングなどのインタラクションのみにして lean(無駄がない) にするのがよさげ。

export class HeroService {
  private heroes: Hero[] = [];

  constructor(
    private backend: BackendService,
    private logger: Logger) { }

  getHeroes() {
    this.backend.getAll(Hero).then( (heroes: Hero[]) => {
      this.logger.log(`Fetched ${heroes.length} heroes.`);
      this.heroes.push(...heroes); // fill cache
    });
    return this.heroes;
  }
}

サービスはコンポーネントに一度加えられると、そのコンポーネントに付随する子供コンポーネントでも参照することができる。そのためルートコンポーネントで読み込ませたサービスのインスタンスは全てのコンポーネントで使用可能になる。

もし、複数のサービスのインスタンスを生成したい場合は以下のようにキャッシュさせる仕組みを整えてあげれば可能。

複数のHeroサービスのインスタンスを管理するHeroCheServiceを定義。

@Injectable()
export class HeroCacheService {
  hero: Hero;
  constructor(private heroService: HeroService) {}

  fetchCachedHero(id: number) {
    if (!this.hero) {
      this.hero = this.heroService.getHeroById(id);
    }
    return this.hero;
  }
}

依存型注入 (DI)

AngularDI機能を提供しており、主にサービスを使用するときにつかう。

コンポーネントの providers プロパティに使用したいサービスを定義する

import { LoggerService }      from './logger.service';
import { UserContextService } from './user-context.service';
import { UserService }        from './user.service';

@Component({
  selector: 'my-app',
  templateUrl: './app.component.html',
  providers: [ LoggerService, UserContextService, UserService ]
})
export class AppComponent {
/* . . . */
}

クラスのコンストラクタでインジェクトする

constructor(logger: LoggerService) {
  logger.logInfo('Creating HeroBiosComponent');
}

参考:
https://angular.io/guide/architecture

5
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
2