Angularのコンポーネントやディレクティブには Lifecycle Hooks(ライフサイクルフック) という仕組みがあり、コンポーネントの変化にあわせてコールバックを設定できます。これによりコンポーネントのデータやビューの変更時の処理を追加できます。
コンポーネント志向のAngularアプリケーションの構築では、Lifecycle Hooks の理解が不可欠です。
今回は Lifecycle Hooks の基本的な仕組みを紹介します。
Lifecycle Hooksとは
記事の冒頭でも説明したように、Lifecycle Hooks はコンポーネントやディレクティブが変化(作成・変更・破棄)するタイミングで実行されるコールバックメソッドの総称です。
例えば、次のようなケースで利用します。
- コンポーネントの初期化時にHttpクライアントでデータを取得する。
- 親コンポーネントの初期化時に、子コンポーネントのDOM要素を取得する。
- コンポーネントの
@Input()
で受け取るデータ内容を検証する。 - 設定したイベントリスナーをコンポーネントが破棄される際に削除する。
Lifecycle Hooksを設定すると、コンポーネント自身が変更を検出したときに自動でコールバックが実行されるため、自前で実行タイミングを設定する手間が省けます。またコンポーネント実装の一貫性を保つことにも繋がります。
Lifecycle Hooksの使い方
ここではコンポーネントの初期化時に実行される ngOnInit
メソッドを見てみましょう。ngOnInit
メソッドは、Angular CLIの ng generate component
コマンドでコンポーネントを作成するとはじめから適用されています。
import { Component, OnInit } from '@angular/core'; // ① import { LoggerService } from './logger.service'; @Component({ ... }) export class PeekABooComponent implements OnInit { // ② constructor(private logger: LoggerService) { } ngOnInit() { // ③ this.log(`OnInit`); } private log(msg:string){ this.logger.log(`${nextId++} ${msg}`); } }
@angular/core
からOnInit
インターフェイスをインポートしています。- コンポーネントのクラスに、
OnInit
インターフェースを実装します。 OnInit
インターフェースを実装すると、ngOnInit
メソッドの定義が必要になります。
Lifecycle Hooks は各メソッドを実装するためのインターフェイスが必要です。
インターフェイスの適用後はインターフェイス名の接頭辞に ng を付けた ngXXXX メソッドが定義できます。例えば OnInit インターフェイスだと ngOnInit メソッドとなります。
インターフェイスを適用しなくてもメソッドを定義できますが、Angularスタイルガイドのルールではインターフェイスを必ず指定することになっていますので、忘れずに適用してください。
Lifecycle Hooksの種類
メソッド名 | 目的と実行タイミング |
---|---|
ngOnInit | 1回目の @Input() でデータバインドされた入力値を初期化後に一度だけ実行します。Httpクライアントによるデータ取得などを含む、コンポーネントの初期化に関する処理を行います。 |
ngOnChanges | @Input() でデータバインドされた入力値を設定・リセットする際に実行します。この処理は入力値が変更するたびに実行され、現在と過去のプロパティを保持した変更オブジェクト(SimpleChanges)を引数で受け取ります。ngOnInitメソッドの前に1回実行され、その後は @Input でデータを受け取る度に実行されます。受け取ったデータ内容を検証する目的で利用します。 |
ngDoCheck | データの変更を検出するたびに実行します。 |
ngAfterContentInit | コンポーネントまたはディレクティブのあるビューに、ng-contentでコンテンツが挿入された後に実行します。 |
ngAfterContentChecked | コンポーネントまたはディレクティブに、ng-contentで挿入されたコンテンツの変更を検知した際に実行します。 |
ngAfterViewInit | コンポーネントのビューとその中の子ビュー、またはディレクティブを含むビューを生成した後に実行します。 ビューに存在するDOMを取得したり、子コンポーネントを参照する際に利用します。 |
ngAfterViewChecked | コンポーネントのビューとその中の子ビュー、またはディレクティブを含むビューの変更を検知した後に実行します。 ビューに存在するDOMや子コンポーネントの変更を監視する際に利用します。 |
ngOnDestroy | コンポーネントまたはディレクティブを破棄する直前に実行します。 RxJSのSubscriptionをunsubscribeしたり、 element.removeEventListener を実行するために利用します。 |
Lifecycle Hooksの実行順序
Lifecycle Hooksは次の順番で実行されます。
- ngOnChanges
- ngOnInit
- ngDoCheck
- ngAfterContentInit
- ngAfterContentChecked
- ngAfterViewInit
- ngAfterViewChecked
- ngOnDestroy
※その他に ngOnChanges はデータを受け取る度、ngDoCheck は ngOnChages の後にも実行されます。
Lifecycle Hooksのライブデモ
以下のライブデモでLifecycle Hooksの動きを試せます。
https://stackblitz.com/angular/enapoxavrmn?embed=1&file=src/app/app.component.html
一番上のPeek-A-Booセクションで、「Create PeekABooComponent」「Update Hero」「Destroy PeekABooComponent」を順にクリックすると Lifecycle Hooksの実行ログを確認できます。
コードと実行結果を見比べてもらえば、わかりやすいです。
【公式日本語ドキュメント】 コンポーネントライフサイクルへのフック