Angular最速マスターへの道 第4章

Blog Single

本日はAngular最速マスターへの道です。
マスターに一歩ずつ近づけるよう今回もやっていきましょう!

第4章目次

  • 共有モジュールの作成
  • Lifecycle Hooks

共有モジュールの作成

第3章でModuleの作成を行いましたが、どのModuleでも使用するようなFormsModuleやCommonModuleをModule毎にimportするのは手間ですよね。
そういう時は共有モジュールを作成することをお勧めします。
必ずしも必須というわけではありませんが、ComponentやModuleを大量に作成する予定のプロジェクトにはあると便利ですし、公式でも推奨されています。
では早速作成しましょう。前回同様Angular CLIのコマンドで作成します。

ng g module shared --spec false

モジュール名は公式と同じSharedModuleで統一して作成していきましょう。
さてModuleの中身を書いて、SharedModuleをimportさせていきます。

// shared.module.ts
import { NgModule } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { CommonModule } from '@angular/common';

@NgModule({
    imports: [
        CommonModule
    ],
    declarations: [
    ],
    exports: [
        CommonModule,
        FormsModule
    ]
})
export class SharedModule { }
@NgModule({
    imports: [
        // CommonModule,
        // FormsModule,
        SharedModule,// ← 代わりに共有モジュールで一括import
    ]
})
export class OtherModule { }

Angularが共通で提供しているDirectiveが必要になるため、CommonModuleは必ずimportに設定してください。
FormsModuleをimportしない理由は、SharedModule内のdeclarationsのComponentにFormsModuleを使う予定がないためです。
必要な場合は随時importが必要になるので注意してください。
今はexportもこれだけですが、今後共有するものが増えた場合はこのSharedModuleに追記していきましょう。
SharedModuleでimportさせることで、修正もここだけで済むので楽になりますね。

Lifecycle Hooks

Lifecycle Hooksとは簡単にいうと、DirectiveやComponentが生成・変更されるタイミングに応じて独自の処理を呼び出す設定をすることです。
WordPressを使ったことがある人は、アクションフックと似たものと考えてもらうとわかりやすいかもしれません。

Angular CLIのコマンドでComponentを作成すると、ngOnInitというメソッドがデフォルトで存在しますよね。
それがこのLifecycle Hooksと呼ばれるものです。
ngOnInit以外にもいくつかメソッドがありますが、まずはざっくりと一連の流れをみていきましょう。

↓自由に入力やボタンを押してみてください
Lifecycle Hooksの一連の流れDEMO

OnChanges

@Input()でバインドされた値の変更を監視するフックです。
DEMOでは子Componentが表示された直後と、inputに文字を入力する度に実行されています。
このフックにはSimpleChangesという引数があり、変更があったかどうかや変更前後の値を判定することができます。
@Inputを使用しないものには使わないですが、親子関係のあるComponent間では使用することの多いフックです。

export class ChildComponent implements OnChanges {
    @Input() text: string;

    ngOnChanges(changes: SimpleChanges): void {
        if (changes.text) {
            console.log('textが変更されました!');
            console.log(`変更前の値: ${changes.text.previousValue}`);
            console.log(`変更後の値: ${changes.text.currentValue}`);
        }
    }
}

OnInit

初期化が終了した後に実行されるフックで、DEMOでは子Component表示ボタンを押すと実行されています。
基本的には一度しか発動しません。
Lifecycle HooksといえばOnInit!くらいに一番使用することが多いです。

export class ChildComponent implements OnInit {
    ngOnInit(): void {
        console.log('初期化完了!');
    }
}

DoCheck

すべての検出と変更ごとに実行されます。
かなり頻繁に実行されてしまうので条件を絞る必要があったり、複雑な処理(たとえば通信)をここで呼んでしまうと何度も実行されてページが重たくなってしまいます。
基本的にあまり使うことがないフックと思って大丈夫です。

AfterContentInitとAfterContentChecked

Componentのみに適用できるフックで、コンポーネント内のコンテンツの初期化後(AfterContentInit)、変更監視(AfterContentChecked)ができます。
@ContentChild()を使用する際に使う場合があります。

@Component({
    selector: 'parent',
    template: `<ng-content></ng-content>`
})
export class ParentComponent implements AfterContentInit, AfterContentChecked {
    @ContentChild(ChildComponent) contentChild: ChildComponent;

    ngAfterContentInit(): void {
        console.log('子コンポーネント初期化完了!');
    }

    ngAfterContentChecked(): void {
        console.log('子コンポーネント変更検知!');
    }
}

AfterViewInitとAfterViewChecked

こちらも先ほど同様、Componentのみに適用できるフックです。
描画初期化後と変更時に実行されます。
AfterViewCheckedはちょっとinputタグにfocusしただけでも実行されるため、こちらも複雑な処理を書くことはあまりオススメしません。

OnDestroy

DirectiveやComponentが破棄される場合に実行されます。
DEMOでは子Componentを削除のボタンを押すと発動しています。
ほかにも、ルーティングで別のページのComponentに遷移した場合にも発動するので、ページ遷移前にキャッシュを残したりする時などにも使用できます。

それぞれのフックをうまく使えば、フォームのバリデーションチェックができたり、Componentの分割もしやすくなります。
難しいと感じる方は、OnInitとOnChangesだけでも覚えてもらえたらといいと思います!
また、発動するタイミングが微妙に異なるのでそこをしっかり覚えておくことをお勧めします。
改めてDEMOを見て確認してみてください!

まとめ

共有モジュールの作成もライフサイクルフックの使用も、Angular使いであれば必ず通る道と言っても過言ではありません。
せっかく公式がデフォルトで用意しているものですので、ありがたくバンバン使ってみましょう!

次章予告

  • ngTemplateOutlet
  • class, styleのバインディング

参考

Angular最速マスターへの道シリーズはGitHubに公開しています。

Posted by Mao Miyaji
千葉にある夢の国を愛して止まない、元「魚のお姉さん」のエンジニア。PHP, TypeScriptメインで、暇さえあれば色々な言語を一かじり。

Other Posts: