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: 共有オブジェクト ファイルを開けません:

推薦する

MySQLトランザクションとMySQLログの詳細な説明

取引特性1. アトミック性: トランザクションの開始後、すべての操作が完了するか、まったく実行されな...

JS で美しい条件式を書く方法についての簡単な説明

目次複数の条件文複数属性オブジェクトスイッチステートメントを置き換えるデフォルトパラメータとデストラ...

JavaScript の継承についてどれくらい知っていますか?

目次序文コンストラクタ、プロトタイプオブジェクト、インスタンスオブジェクトの関係プロトタイプチェーン...

Docker での RocketMQ の詳細なインストールと使用

RocketMQ イメージを検索するには、Docker の hub.docker.com で検索する...

jQuery で呼吸カルーセル効果を実現

この記事では、呼吸カルーセル効果を実現するためのjQueryの具体的なコードを参考までに共有します。...

HTML サブタグと sup タグ

今日はあまり使わないHTMLタグ「subタグ」と「supタグ」を紹介します。定義と使用法: <...

Vue.jsのレンダリング関数の使い方の詳しい説明

Vue では、ほとんどの場合、テンプレートを使用して HTML を作成することを推奨しています。ただ...

HTML リンク アンカー タグと SEO におけるその役割の概要

<a> タグは主に、ハイパーリンクまたはアンカー リンクとも呼ばれるリンクとブックマーク...

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

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

Linuxシステムのログの詳細な紹介

目次1. ログ関連サービス2. システム内の共通ログファイル1. ログ関連サービスCentOS 6....

CSS を使用して 3 列レイアウトを実装するサンプル コード。中央の列は適応型で、テキスト サイズに応じて幅が変わります。

Baiduのインタビューで遭遇する質問は、次のレイアウト効果を達成する必要がある。 中央の紫色の列...

MySQL アーキテクチャのナレッジポイントの概要

1. データベースとデータベースインスタンスMySQL の研究では、データベースとデータベース イン...

要素 el-table テーブルの二次カプセル化 (テーブルの高さの調整付き)

序文会社でのインターンシップ中、フロントエンド開発にはvue+element-uiフレームワークを使...

インデックスは MySQL クエリ条件で使用されますか?

雇用主から MySQL クエリ条件でインデックスが使用されるかどうかを尋ねられた場合、どのように答え...

IE環境では、divの高さはフォントの高さよりも大きくなければならないと規定されています。

コードをコピーコードは次のとおりです。 <div class="content&qu...