「Angular 2」コンポーネントのライフサイクルを知って使いこなす
次世代Webアプリケーションフレームワーク「Angular」の活用 第7回
ダウンロード サンプルファイル (31.0 KB)
ビューの初期化と変更に対応するngAfterViewInit、ngAfterVieweChecked
ngAfterViewInitは、コンポーネントの画面(ビュー)が初期化されたとき、ngAfterViewCheckedはビューが変更されてAngular 2が検証を完了したタイミングで実行されます。図8のサンプル(004-afterview)で、実行の様子を説明します。
このサンプルを実行すると、画面表示時点でngAfterViewInitとngAfterViewCheckedが実行されます。また、テキストボックスの値を変更すると、ngAfterViewCheckedがその都度実行されます。
このサンプルでは、まずリスト6の子コンポーネント(ChildComponent)を利用します。このコンポーネントには1個のテキストボックスと、それに対応するchildInputプロパティが存在します。
@Component({
selector: "lifecycle-child"
template: `
<div class="component">
<h4>ChildComponent</h4>
childInput: <input type="text" [(ngModel)]="childInput">
</div>
`,
})
export class ChildComponent {
// テキストボックスへの入力値
childInput:string="初期値";
}
子コンポーネントを参照するコンポーネントの実装はリスト7のようになります。
export class LifeCycleComponent
implements AfterViewInit, AfterViewChecked {
// 子コンポーネント ...(1)
@ViewChild(ChildComponent) viewChild: ChildComponent;
// 画面に表示する文字列 ...(2)
valueFromChild:string="";
// View初期化後に呼ばれる ...(3)
ngAfterViewInit() {
console.debug("ngAfterViewInit:" + this.viewChild.childInput);
}
// View更新ごとに呼ばれる ...(4)
ngAfterViewChecked() {
console.debug("ngAfterViewChecked:" + this.viewChild.childInput);
this.displayValueFromChild();
}
// 子コンポーネントのchildInputの値を画面に表示する ...(5)
displayValueFromChild() {
// この時点でビューの処理が終わっているので、実行を遅らせる ...(6)
if (this.valueFromChild != this.viewChild.childInput) {
setTimeout(() => {
this.valueFromChild=this.viewChild.childInput;
}, 0);
}
// このようにすると、入力がすぐに画面に反映されない ...(7)
// this.valueFromChild = this.viewChild.childInput;
}
}
(1)の@ViewChildデコレーターで、子コンポーネントをviewChild変数で参照できるようにしています。(2)はデータバインディングで画面表示する文字列変数です。(3)と(4)がライフサイクルフックの実装です。ここではviewChild.childInputの内容をデバッグログに出力しつつ、(4)では(5)で実装されるdisplayValueFromChildメソッドを実行しています。
displayValueFromChildメソッド(5)は、子コンポーネントのchildInputプロパティを、自身のvalueFromChildにコピーして、画面表示するメソッドです。ngAfterViewCheckedライフサイクルフックの実行時点では、ビューの処理が全て完了しているため、(6)のように、Angularが次の変更検知を行うタイミングまで、setTimeoutで画面表示処理を遅らせる必要があります。
なお、(7)のように画面表示処理を遅らせないと、図10のように、内容がすぐに画面に反映されなくなります。テキストボックスからフォーカスを外すと、Angular 2が画面の変更を検知して、入力内容を画面に反映します。
外部コンテンツの初期化と変更に対応するngAfterContentInit、ngAfterContentChecked
ngAfterViewInit、ngAfterViewCheckedがビューに関連するのに対して、外部コンテンツのライフサイクルフックが、ngAfterContentInitとngAfterContentCheckedです。
コンポーネント外部からコンテンツを取り込むContent Projection
Angular 2では、コンポーネントのタグ内に記述された外部コンテンツを、コンポーネント内に取り込む「Content projection」が利用できます(AngularJS 1の「Transclusion」に対応します)。例えば、リスト6の子コンポーネントに対応する<lifecycle-child>タグを、lifecycleコンポーネントの<lifecycle>タグ内に記述できます。
<lifecycle> <!-- 子コンポーネントの表示 --> <lifecycle-child></lifecycle-child> </lifecycle>
外部コンテンツの内容は、lifecycleコンポーネントのテンプレートに記述された<ng-content>タグの箇所に反映されます。
ngAfterContentInit、ngAfterContentCheckedは、このように記述した外部コンテンツの初期化と変更に対応するライフサイクルフックです。
ngAfterContentInit、ngAfterContentCheckedの実装例
図11のサンプル(005-aftercontent)で、ngAfterContentInit、ngAfterContentCheckedが実行される様子を説明します。
表示内容、デバッグログの出力タイミングは図8、9と似ていますが、このサンプルでは、ngAfterContentInit、ngAfterContentCheckedライフサイクルフックで処理を行います。
子コンポーネントを呼び出すコンポーネントの実装はリスト9のようになります。
export class LifeCycleComponent
implements AfterContentInit, AfterContentChecked {
// 子コンポーネント ...(1)
@ContentChild(ChildComponent) contentChild: ChildComponent;
// 画面に表示する文字列
valueFromChild:string="";
// コンテンツ初期化後に呼ばれる ...(2)
ngAfterContentInit() {
console.debug("ngAfterContentInit:" + this.contentChild.childInput);
}
// コンテンツ更新ごとに呼ばれる ...(3)
ngAfterContentChecked() {
console.debug("ngAfterContentChecked:" + this.contentChild.childInput);
this.displayValueFromChild();
}
// 子コンポーネントのchildInputの値を画面に表示する ...(4)
displayValueFromChild() {
// AfterViewフックの前なので、バインディング変数を直接変更できる ...(5)
this.valueFromChild = this.contentChild.childInput;
}
}
子コンポーネントChildComponentは、対応する<lifecycle-child>タグが外部コンテンツとして記述されているので、(1)の@ContentChildデコレーターで参照します。(2)と(3)がライフサイクルフックの実装です。画面を更新する処理(4)は、ngAfterContentCheckedの実行時点でビューのライフサイクルフックがまだ実行されていないため(図1参照)、リスト7と違って(5)のように直接画面を書き換えることができます。このように、外部コンテンツのライフサイクルフックは、ビューのライフサイクルフックより前に実行されることに注意してください。
まとめ
本記事では、Angular 2のコンポーネントで定義されているライフサイクルと、ライフサイクルフックのメソッド実装方法を説明しました。ライフサイクルを理解してライフサイクルフックを実装すれば、状態に合った適切なタイミングで処理を実行できます。
参考資料
この記事は参考になりましたか?
既に会員の方はを行ってください。
- 次世代Webアプリケーションフレームワーク「Angular」の活用連載記事一覧
- この記事の著者
-
WINGSプロジェクト 吉川 英一(ヨシカワ エイイチ)
<WINGSプロジェクトについて>有限会社 WINGSプロジェクトが運営する、テクニカル執筆コミュニティ(代表 山田祥寛)。主にWeb開発分野の書籍/記事執筆、翻訳、講演等を幅広く手がける。 2026年時点での登録メンバは約50名で、現在も執筆メンバを募集中。興味のある方は、どしどし応募頂きたい。著書、記事多数。 RSS X: @WingsPro_info(公式)、@WingsPro_info/wings(メンバーリスト) Facebook
※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です
-
山田 祥寛(ヤマダ ヨシヒロ)
静岡県榛原町生まれ。一橋大学経済学部卒業後、NECにてシステム企画業務に携わるが、2003年4月に念願かなってフリーライターに転身。Microsoft MVP for Visual Studio and Development Technologies。執筆コミュニティ「WINGSプロジェクト」代表。主な著書に「独習シリーズ(Java・C#・Python・PHP・Ruby・JSP&サーブレットなど)」「速習シリーズ(ASP.NET Core・Vue.js・React・TypeScript・ECMAScript、Laravelなど)」「改訂3版JavaScript本格入門」「これからはじめるLaravel実践入門」「はじめてのAndroidアプリ開発 Kotlin編 」他、著書多数。
※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です
この記事は参考になりましたか?
この記事をシェア
