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

推薦する

Linuxで静的ネットワーク接続を構成する方法

Linux システムのネットワーク接続を構成するのは難しい場合があります。幸いなことに、多くの新しい...

Vue の img の src 画像アドレスの動的スプライシングの問題について

Vue での img の動的スプライシングを見てみましょう。src 画像アドレス、具体的な内容は次の...

React構成サブルーティングの実装

1. コンポーネント First.js にはサブコンポーネントがあります。 './Admin...

Docker を使用した SQL Server の実行の実装

現在、.net Core はクロスプラットフォームであり、誰もが Linux と Docker を使...

ブラウザは関連するHTTPヘッダーをキャッシュし、HTTPリクエストの数を最小限に抑えます。

最近、Yahoo の 34 の黄金律を読み、ウェブサイトのパフォーマンスを最適化する方法を学びました...

MySQL バージョンは、2 つのタイムスタンプ型の値をサポートしていないバージョンよりも低いです。

MySQL エラー:エラー コード: 1293 テーブル定義が正しくありません。CURRENT_T...

JSを段階的に学ぶ方法についての簡単な説明

目次概要1. jsの位置づけを明確に理解する2. 明確な学習パス3. 自己規律と粘り強さ4. 練習し...

バックアップと削除のためにリアルタイムでステートメントを検出するMySQLトリガーの考え方の詳細な説明

問題の説明: ユーザーは、テーブルに「違反」という単語を含むフィールドが時々表示されることを要求して...

ElementUIカスタムCSSスタイルが有効にならない問題を解決する

例えば、入力ボックスがあります <el-入力 ref="mySearch"...

MySQLにインデックスを追加する方法

インデックスの簡単な紹介は次のとおりです。インデックスを追加する目的は、データベース クエリのパフォ...

JSはビデオの再生速度を制御するための簡単なサンプルコードを実装します

導入以前、ある問題に気づきました。学習ビデオを視聴しているとき、動きが遅すぎる、先生が黒板に書くのに...

React+Typescriptはカウントダウンフックメソッドを実装します

まず、setIntervalはフックとしてカプセル化されます👇 'react' から...

WebプロジェクトをIdeaにインポートし、Tomcatに公開する問題を解決します

Idea は既存の Web プロジェクトをインポートして Tomcat に公開しますが、Tomcat...

ウェブサイト上で flv/MP4 やその他のビデオ ファイルを再生できない問題は、MIME タイプに関連しています。

ウェブサイトを作成している際に、flv や MP4 形式などのビデオ ファイルはローカルでは正常に再...

Docker で Tomcat を使用して Web アプリケーションを迅速にデプロイする方法の例

Docker の基本的な操作を学習した後、コンテナにいくつかの基本的なアプリケーションをデプロイして...