Angularコンポーネントライフサイクルの詳細説明(I)

Angularコンポーネントライフサイクルの詳細説明(I)

概要

コンポーネント宣言サイクルとAngularの変更検出メカニズム

赤いメソッドは 1 回だけ実行されます。

変更検出中に実行されるグリーン メソッドは、コンポーネントの初期化中に実行されるグリーン メソッドと同じです。

全部で9つの方法があります。

各フックは、@angular/core ライブラリで定義されたインターフェースです。

'@angular/core' から Component、OnInit をインポートします。

@成分({
  セレクター: 'app-life',
  テンプレート URL: './life.component.html',
  スタイル URL: ['./life.component.css']
})
LifeComponentクラスをエクスポートし、OnInitを実装します。

  コンストラクタ() { }

  ngOnInit() {
  }

}

インターフェースは必須ではありませんが、Angular はフックメソッドを検出するとそれを実行するので、インターフェースを記述することをお勧めします。

1. フックの呼び出し順序

'@angular/core' から { Component、OnInit、OnChanges、DoCheck、AfterContentInit、AfterContentChecked、AfterViewInit、AfterViewChecked、OnDestroy、Input、SimpleChange、SimpleChanges } をインポートします。

let logIndex: number = 1; //Counter@Component({
  セレクター: 'app-life',
  テンプレート URL: './life.component.html',
  スタイル URL: ['./life.component.css']
})
エクスポートクラス LifeComponent は OnInit、OnChanges、DoCheck、AfterContentInit を実装します。
  、AfterContentChecked、AfterViewInit、AfterViewChecked、OnDestroy {
  @入力()
  名前: 文字列;

  logIt(メッセージ: 文字列) {
    console.log(`# ${logIndex++} ${msg}`);
  }
  コンストラクタ() {
    this.logIt("コンストラクタの name プロパティの値は: " + this.name);
  }

  ngOnInit() {
    this.logIt("OnInit の name プロパティの値は: " + this.name);
  }

  ngOnChanges(changes: SimpleChanges): void { // SimpleChanges オブジェクトを渡します let name = changes['name'].currentValue;
    this.logIt("ngOnChanges の name 属性の値は: " + this.name);
  }

  ngDoCheck(): void {
    this.logIt("DoCheck");
  }

  ngAfterContentInit() {
    this.logIt("ngAfterContentInit");
  }

  ngAfterContentChecked() {
    this.logIt("ngAfterContentChecked");
  }

  ngAfterViewInit() {
    this.logIt("ngAfterViewInit");
  }

  ngAfterViewChecked() {
    this.logIt("ngAfterViewChecked");
  }
  ngOnDestroy() {
    this.logIt("ngOnDestory");
  }
} 

初期化ロジックが入力プロパティの値に依存する場合、初期化ロジックはコンストラクターではなく ngOnInit に記述する必要があります。

DoCheck は、Angular のすべての変更検出サイクル中に呼び出されます。

ngAfterContentInit と ngAfterContentChecked は、テンプレートとコンポーネント コンテンツの投影に関連しています。

ngAfterViewInit と ngAfterViewChecked は、コンポーネント テンプレートと初期化ビューに関連しています。

2. onChangesフック

親コンポーネントは、子コンポーネントの入力パラメータを初期化または変更するときに呼び出されます。

まず、js の可変オブジェクトと不変オブジェクトを理解する必要があります。

//文字列は不変です var greeting = "Hello";
挨拶 = "こんにちは世界";
//オブジェクトは変更可能です var user = { name: "Tom" };
ユーザー名 = "ジェリー";

例:

子コンポーネントには 3 つのプロパティがあり、そのうち 2 つは入力プロパティです。

親コンポーネントには、Tom のユーザー オブジェクトである greeting プロパティと name プロパティがあります。

親コンポーネントは入力プロパティを変更する必要があるため、greeting と user.name は双方向にバインドされます。

<div class="parent">
    <h2>私は親コンポーネントです</h2>
    <div>挨拶: <input type="text" [(ngModel)]="greeting"></div>
    <div>
      名前:
      <input type="text" [(ngModel)]="ユーザー名">
    </div>
    <app-child [greeting]="greeting" [(user)]="user"> </app-child>
</div>

親コンポーネントが 2 つの入力の値を変更すると、子コンポーネントに渡される値も変更されます。子コンポーネントに渡される入力プロパティの値が変化すると、ngOnChanges() がトリガーされます。

親コンポーネントは子コンポーネントを初期化します。初期化中に ngOnChanges() を 1 回呼び出します。初期化後、子コンポーネントの挨拶は、親コンポーネントの挨拶の値である Hello になります。

ユーザーは Tom という名前属性を持つオブジェクトになります。

入力属性の値を変更し、親コンポーネントの greeting を Helloa に変更します。

Angular の変更検出は、不変オブジェクト、つまり greeting の値を更新し、ngOnChanges() メソッドを呼び出します。greeting の値は、以前の hello から Helloa に変更されます。

user.name を Tomb に変更すると、コンソールに新しいメッセージは表示されなくなります。

ユーザーは可変オブジェクト ユーザーのプロパティのみを変更したため、ユーザー オブジェクト自体への参照は変更されず、onChanges() メソッドは呼び出されませんでした。

可変オブジェクトのプロパティの変更によって ngOnChanges() メソッドの呼び出しはトリガーされませんが、Angular の変更検出メカニズムによってコンポーネント内の各オブジェクトのプロパティの変更がキャプチャされるため、子コンポーネントのユーザー オブジェクトのプロパティは変更されます。

子コンポーネントの message プロパティを変更しても、子コンポーネントの onChanges() メソッドは呼び出されません。メッセージは入力属性ではないためです。 ngOnChanges() は、入力プロパティが変更された場合にのみ呼び出されます。

3. 変更検出メカニズムとDoCheck()フック

変更検出はzone.jsによって実装されます。コンポーネント プロパティの変更がページの変更と同期されていることを確認します。ブラウザで発生する非同期イベント (ボタンのクリック、データの入力、サーバーからのデータの戻り、setTimeout() メソッドの呼び出し) により、変更検出がトリガーされます。

変更検出が実行されると、コンポーネント テンプレート上のすべてのバインディング関係が検出されます。コンポーネントのプロパティが変更された場合、それにバインドされているテンプレートの対応する領域を更新する必要がある場合があります。

注意: 変更検出メカニズムは、コンポーネント プロパティの変更をテンプレートに反映するだけです。変更検出メカニズム自体は、コンポーネント プロパティの値を変更することはありません。

2 つの変更検出戦略。

  • デフォルトでは、コンポーネント ツリー全体をチェックして変更を検出します。
  • OnPush は、入力プロパティが変更された場合にのみ、コンポーネントとそのサブコンポーネントを検出します。

Angular アプリケーションは、メイン コンポーネントをルートとするコンポーネント ツリーです。各コンポーネントは変更検出器を生成します。いずれかの変更検出器が変更を検出すると、zone.js はコンポーネントの変更チェック戦略に基づいてコンポーネントをチェックし (つまり、doCheck() フックを呼び出し)、コンポーネントのテンプレートを更新する必要があるかどうかを判断します。

DoCheck は、変更がどのコンポーネントで発生したかに関係なく、ルート コンポーネントから始まるすべてのコンポーネント ツリーをチェックします。

例:

user.name などの変更可能なオブジェクトの属性の変更を監視します。

変更前のユーザー名を保存するために子に oldUsername を追加し、ユーザー名が変更されたかどうかをマークするために changeDetected 属性を追加します。デフォルト値は false です。 noChangeCount カウンターのデフォルトは 0 です。

'@angular/core' から Component、OnInit、Input、OnChanges、SimpleChanges、DoCheck をインポートします。

@成分({
  セレクタ: 'app-child',
  テンプレート URL: './child.component.html',
  スタイル URL: ['./child.component.css']
})
エクスポートクラス ChildComponent は OnInit、OnChanges、DoCheck を実装します {

  @入力()
  挨拶: 文字列;

  @入力()
  ユーザー: { 名前: 文字列 };

  message: string = "初期化メッセージ";
  oldUsername: 文字列;
  変更検出: ブール値 = false;
  変更回数なし: 数値 = 0;

  コンストラクタ() { }

  ngOnInit() {
  }

  ngOnChanges(変更: SimpleChanges): void {
    console.log(JSON.stringify(変更、null、2));
  }

  ngDoCheck() {
    if (this.user.name !== this.oldUsername) {
      this.changeDetected = true;
      console.log("DoCheck: user.name が " + this.oldUsername + " から " + this.user.name に変更されます);
      this.oldUsername = this.user.name;
    }
    if (this.changeDetected){//変更カウンタが0にクリアされました
      this.noChangeCount = 0;
    } else{// 変更なし this.noChangeCount++;
      console.log("DoCheck: user.name が変更されていないときに ngDoCheck メソッドが呼び出されました" + this.noChangeCount + "回")
    }
    this.changeDetected = false; //最後に、変更の有無に関係なくフラグがリセットされます}

} 

ページの読み込みが完了しました: user.name が変更されていないときに DoCheck メソッドが 1 回呼び出されました。

マウスをクリックしても値は変更されません。クリックすると変更検出メカニズムがトリガーされ、すべてのコンポーネントの DoCheck が呼び出されます。

Tom を Tomb に変更すると、DoCheck は Tom が Tomb に変更されたことを検出します。

DoCheck() フックは user.name が変更されたときに検出できますが、ngDoCheck() フックは非常に頻繁に呼び出されるため、注意して使用する必要があります。これは、変更が発生したときに、変更検出サイクルごとに呼び出されます。

ngDoCheck() の実装は非常に効率的かつ軽量である必要があります。そうでないと、パフォーマンスの問題が簡単に発生してしまいます。

同様に、Check キーワードを持つすべてのフック メソッドは、細心の注意を払って使用する必要があります。 ngDoCheck、ngAfterContentChecked、ngAfterViewChecked。

以上がAngularコンポーネントライフサイクルの詳しい説明(パート1)です。Angularコンポーネントライフサイクルの詳細については、123WORDPRESS.COMの他の関連記事にも注目してください!

以下もご興味があるかもしれません:
  • Angular2コンポーネントのライフサイクルフックについての簡単な説明
  • Angular4のライフサイクルフックについての簡単な説明
  • Angularのライフサイクルフックの理解に関する簡単な説明
  • Angular2ライフサイクルフック関数の詳細な紹介
  • AngularJS のスコープ、継承構造、イベント システム、ライフ サイクルに関する詳細な説明
  • AngularJS フレームワークにおける $scope の役割とライフサイクルの詳細な分析
  • AngularJS のライフサイクルと遅延処理の簡単な分析

<<:  Dockerを使用してLaravel開発環境を構築するための完全な手順

>>:  MongoDB の起動エラーを解決します: 共有ライブラリのロード中にエラーが発生しました: libstdc++.so.6: 共有オブジェクト ファイルを開けません:

推薦する

Telnet は Alpine イメージの busybox-extras に移動されました

Alpine イメージの telnet はバージョン 3.7 以降、busybox-extras パ...

Javascript で SessionStorage と LocalStorage を使用する方法

目次序文SessionStorage と LocalStorage の紹介SessionStorag...

ウェブフロントエンド開発者が知っておくべき 9 つの実用的な CSS プロパティ

1. 角を丸くする今日の Web デザインは、常に最新の開発テクノロジーに追随しており、HTML5 ...

Webpack での publicPath の使用法の詳細な説明

目次出力出力パス出力.publicPath webpack-dev-server の publicP...

Docker Secretの管理と使用の詳細な説明

1. Docker Secretとは1. シナリオ表示MySQL サービスなど、一部のサービスではパ...

MySQLのスイッチングデータ保存ディレクトリの実装方法

MySQLのスイッチングデータ保存ディレクトリの実装方法今日、仕事中に、mysql が保存されている...

HTML で js を使用してローカル システム時間を取得する

コードをコピーコードは次のとおりです。 <div id="名前"> ...

CSS 3D からソースコードによる空間座標軸へ

かつて、サイコロを振るゲームについて話しました。その時は、steps 属性 + スプライト画像を使用...

LinuxシステムでのSystemC環境設定方法

以下はcentos7での設定方法ですsystemc ソース パッケージをダウンロード: System...

Vue 開発者向けの VSCode 拡張機能ベスト 7

適切な VS Code 拡張機能を Visual Studio に追加すると、開発者としての作業がは...

mysql-5.7.21-winx64 無料インストール版のインストール - Windows チュートリアル詳細説明

1 ダウンロードアドレスは https://dev.mysql.com/downloads/mysq...

MySQL inndbジョイントインデックスを正しく使用する方法を徹底的に理解するためのケーススタディ

最近確認された5件のデータを照会するビジネスがあります。 `id`、`title` を選択 `th_...

Windows で MySQL データベースを別のディスクに移動する

序文今日、MySQL をインストールしたところ、データベース ストレージがデフォルトで C ドライブ...

MySQL トランザクション分離レベルと MVCC の詳細な説明

目次トランザクション分離レベル同時トランザクション実行中に発生した問題SQL標準の4つの分離レベルM...

mysql IS NULL インデックスケースの説明を使用する

導入MySQL の SQL クエリ ステートメントで is null、is not null、!= ...