ホームページ  >  記事  >  ウェブフロントエンド  >  Angular の変更検出とは何ですか?変更検出はどのような状況でトリガーされますか?

Angular の変更検出とは何ですか?変更検出はどのような状況でトリガーされますか?

青灯夜游
青灯夜游転載
2022-12-13 20:06:002032ブラウズ

Angular における変更検出とは何ですか?次の記事では、変更検出について説明し、変更検出が発生する状況を紹介します。

Angular の変更検出とは何ですか?変更検出はどのような状況でトリガーされますか?

#変更検出とは何ですか?

簡単に言うと、変更検出は、ビューとモデルの間にバインドされた値が変更されたかどうかを検出するために Angular によって使用されます。モデル内の値が変更されたことが検出された場合、逆に、ビュー上の値が変更されたことが検出されると、対応するバインディング関数がコールバックされます。 [関連チュートリアルの推奨事項: "angular チュートリアル"]

つまり、モデルの変更とビューの一貫性を保つメカニズムです。このメカニズムは変更検出と呼ばれます。

Angular では、開発者は特定の DOM 更新に集中する必要はなく、ビジネスだけに集中できます。これは、Angular がこの部分の作業を代わりに行ってくれるからです。

Angular を使用せず、ネイティブ JS で開発する場合は、DOM を手動で更新する必要があります。最初に例を見てみましょう。

<html>
  <div id="dataDiv"></div>
  <button id="btn">updateData</button>
  <canvas id="canvas"></canvas>
  <script>
    let value = &#39;initialValue&#39;;
    // initial rendering
    detectChange();

    function renderHTML() {
      document.getElementById(&#39;dataDiv&#39;).innerText = value;
    }

    function detectChange() {
      const currentValue = document.getElementById(&#39;dataDiv&#39;).innerText;
      if (currentValue !== value) {
        renderHTML();
      }
    }

    // Example 1: update data inside button click event handler
    document.getElementById(&#39;btn&#39;).addEventListener(&#39;click&#39;, () => {
      // update value
      value = &#39;button update value&#39;;
      // call detectChange manually
      detectChange();
    });

    // Example 2: HTTP Request
    const xhr = new XMLHttpRequest();
    xhr.addEventListener(&#39;load&#39;, function() {
      // get response from server
      value = this.responseText;
      // call detectChange manually
      detectChange();
    });
    xhr.open(&#39;GET&#39;, serverUrl);
    xhr.send();

    // Example 3: setTimeout
    setTimeout(() => {
      // update value inside setTimeout callback
      value = &#39;timeout update value&#39;;
      // call detectChange manually
      detectChange();
    }, 100);

    // Example 4: Promise.then
    Promise.resolve(&#39;promise resolved a value&#39;).then(v => {
      // update value inside Promise thenCallback
      value = v;
      // call detectChange manually
      detectChange();
    }, 100);

    // Example 5: some other asynchronous APIs
    document.getElementById(&#39;canvas&#39;).toBlob(blob => {
      // update value when blob data is created from the canvas
      value = `value updated by canvas, size is ${blob.size}`;
      // call detectChange manually
      detectChange();
    });
  </script>
</html>

上記の例では、データを更新した後、detectChange() を呼び出してデータが変更されたかどうかを確認する必要があります。データが変更された場合は、更新されたデータを反映するために HTML がレンダリングされます。もちろん、Angular の では、開発者はこれらの手順を気にする必要はありません。データを更新するだけでよく、DOM は自動的に を更新します。これが変化検出です。

変更検出はどのような状況で発生しますか?

変更検出の鍵は、境界値が変更されたかどうか、またその変更がどのような理由で変更されたかを最小の粒度で検出する方法です。状況によって、これらのバインディングの値が変更されることがありますか?

日々の開発に基づいたいくつかのシナリオを見てみましょう。

シナリオ 1

コンポーネントの初期化:

Angular アプリケーションを開始すると、Angular がロードされますブートストラップ コンポーネントを呼び出し、ApplicationRef.tick() をトリガーして変更検出とビューのレンダリングを呼び出します。

#シナリオ 2

DOM および BOM イベント:

DOM イベントまたは BOM イベントリスナーは、Angular コンポーネントのデータを更新でき、以下の例に示すように、変更検出をトリガーすることもできます。

@Component({
  selector: "counter",
  template: `
    Count:{{ count }}
    <br />
    <button (click)="add()">Add</button>
  `,
})
export class CounterComponent {
  count = 0;

  constructor() {}

  add() {
    this.count = this.count + 1;
  }
}

ビュー上の補間式によってカウンターの count 属性をバインドしました。ボタンをクリックすると count 属性の値が変更され、バインドされた値も変更されます。

シナリオ 3

HTTP データ リクエスト:

@Component({
    selector: "todos",
    template: ` <li *ngFor="let item of todos">{{ item.titme }}</li> `,
  })
  export class TodosComponent implements OnInit {
    public todos: TodoItem[] = [];

    constructor(private http: HttpClient) {}

    ngOnInit() {
      this.http.get<TodoItem[]>("/api/todos").subscribe((todos: TodoItem[]) => {
        this.todos = todos;
      });
    }
  }

これを todos コンポーネントでリクエストしますサーバーが Ajax リクエストを送信し、リクエストが結果を返すと、ビューにバインドされている todo の値が変更されます。

シナリオ 4

その他のマクロ タスクとマイクロ タスク:

setTimeout() などまたは setInterval()。 setTimeout() マクロタスクのコールバック関数でデータを更新することもできます。

@Component({
  selector: &#39;app-root&#39;,
  template: &#39;<div>{{data}}</div>&#39;;
})
export class AppComponent implements OnInit {
  data = &#39;initial value&#39;;

  ngOnInit() {
    setTimeout(() => {
      // user does not need to trigger change detection manually
      this.data = &#39;value updated&#39;;
    });
  }
}

実際の開発では、バインドされた値を変更するために特定の関数内でタイマーが呼び出されることがあります。

別の例は

Promise.then() です。他の非同期 API (fetch など) は Promise オブジェクトを返すため、then() コールバック関数でもデータを更新できます。

@Component({
  selector: &#39;app-root&#39;,
  template: &#39;<div>{{data}}</div>&#39;;
})
export class AppComponent implements OnInit {
  data = &#39;initial value&#39;;

  ngOnInit() {
    Promise.resolve(1).then(v => {
      // user does not need to trigger change detection manually
      this.data = v;
    });
  }
}

シナリオ 5

その他の非同期操作:

Except

addEventListener() 、setTimeout() および Promise.then()、およびデータを非同期的に更新できるその他の操作。たとえば、WebSocket.onmessage()Canvas.toBlob() などです。

上記の状況には 1 つの共通点があることを見つけるのは難しくありません。つまり、

バインディング値の変更を引き起こすイベントは 非同期イベント です。 非同期操作が発生している限り、Angular は状態が変更された可能性があると判断し、変更検出を実行します

考察: 他にどのような非同期イベントがあるでしょうか?

これらは、アプリケーションがデータを変更する可能性がある最も一般的なシナリオをカバーしています。 Angular は、データが変更された可能性があることを検出するたびに、変更検出を実行します。変更検出の結果として、DOM はこの新しいデータに基づいて更新されます。 Angular はさまざまな方法で変更を検出します。コンポーネントの初期化の場合、Angular は明示的な変更検出を呼び出します。 非同期操作の場合、Angular はゾーンを使用してデータが変更される可能性のある変更を検出し、自動的に変更検出を実行します。

これらの非同期イベントをサブスクライブするにはどうすればよいですか?次回の記事もお楽しみに。

プログラミング関連の知識について詳しくは、プログラミング教育をご覧ください。 !

以上がAngular の変更検出とは何ですか?変更検出はどのような状況でトリガーされますか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事はjuejin.cnで複製されています。侵害がある場合は、admin@php.cn までご連絡ください。