目次
Angular の DOM 更新メカニズム
ホームページ ウェブフロントエンド jsチュートリアル Angular 変更検出における DOM 更新メカニズムの簡単な分析

Angular 変更検出における DOM 更新メカニズムの簡単な分析

Dec 12, 2022 pm 07:44 PM
フロントエンド angular.js 変化の検出 DOM 更新メカニズム

Angular 変更検出における DOM 更新メカニズムの簡単な分析

変更検出は Angular の重要な部分であり、モデルとビュー間の同期を維持します。日々の開発プロセスでは、変更検出について知る必要はありません。Angular がこの部分の作業を完了するのに役立ち、開発者はビジネスの実装により集中できるようになり、開発効率と開発エクスペリエンスが向上します。ただし、フレームワークを詳しく使用したい場合、または単に関数を実装するのではなく高パフォーマンスのコードを作成したい場合は、変更検出について理解する必要があります。これは、フレームワークの理解を深め、エラーをデバッグし、パフォーマンスを向上させるのに役立ちます。 [関連チュートリアルの推奨事項: "angular チュートリアル "]

Angular の DOM 更新メカニズム

最初に小さな例を見てみましょう。

#ボタンをクリックすると、name 属性が変更され、DOM が新しい name 値で自動的に更新されます。

ここで質問ですが、name の値を変更して DOM に innerText を出力すると、どのような値になりますか?

import { Component, ViewChild, ElementRef } from '@angular/core';

@Component({
  selector: 'my-app',
  templateUrl: './app.component.html',
  styleUrls: [ './app.component.css' ]
})
export class AppComponent  {
  name = 'Empty';

  @ViewChild('textContainer') textContainer: ElementRef;

  normalClick(): void {
    this.name = 'Hello Angular';

    console.log(this.textContainer.nativeElement.innerText);
  }
}
ログイン後にコピー

正解できましたか?

では、これら 2 つのコードでは一体何が起こったのでしょうか?

ネイティブ JS を使用してこのコードを記述する場合、ボタンをクリックしてもビューは絶対に変わりませんが、Angular ではビューが変更されるのに、なぜ自動的にビューが更新されるのでしょうか? 毛糸?これはzone.jsというライブラリと切り離せないもので、簡単に言うと値が変化するイベントの処理を行うもので、これについては次のセクションで詳しく説明しますので、今はこれだけ知っていれば十分です。

このライブラリにこの処理を実行させたくない場合、Angular にはzone.js を無効にする方法も用意されています。

main.ts でzone.js を無効にすることができます。

import { enableProdMode } from '@angular/core';
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';

import { AppModule } from './app/app.module';
import { environment } from './environments/environment';

if (environment.production) {
  enableProdMode();
}

platformBrowserDynamic().bootstrapModule(AppModule, {
  ngZone: 'noop'
})
  .catch(err => console.error(err));
ログイン後にコピー

zone.js を無効にすると、ビューは更新されません。ソース コードに移動して、ビューの更新に関連するコードを見つけます。

 */
class ApplicationRef {
    /** @internal */
    constructor(_zone, _injector, _exceptionHandler, _initStatus) {
        this._zone = _zone;
        this._injector = _injector;
        this._exceptionHandler = _exceptionHandler;
        this._initStatus = _initStatus;
        /** @internal */
        this._bootstrapListeners = [];
        this._views = [];
        this._runningTick = false;
        this._stable = true;
        this._destroyed = false;
        this._destroyListeners = [];
        /**
         * Get a list of component types registered to this application.
         * This list is populated even before the component is created.
         */
        this.componentTypes = [];
        /**
         * Get a list of components registered to this application.
         */
        this.components = [];
        this._onMicrotaskEmptySubscription = this._zone.onMicrotaskEmpty.subscribe({
            next: () => {
                this._zone.run(() => {
                    this.tick();
                });
            }
        });
        ...
    }

/**
     * Invoke this method to explicitly process change detection and its side-effects.
     *
     * In development mode, `tick()` also performs a second change detection cycle to ensure that no
     * further changes are detected. If additional changes are picked up during this second cycle,
     * bindings in the app have side-effects that cannot be resolved in a single change detection
     * pass.
     * In this case, Angular throws an error, since an Angular application can only have one change
     * detection pass during which all change detection must complete.
     */
    tick() {
        NG_DEV_MODE && this.warnIfDestroyed();
        if (this._runningTick) {
            const errorMessage = (typeof ngDevMode === 'undefined' || ngDevMode) ?
                'ApplicationRef.tick is called recursively' :
                '';
            throw new RuntimeError(101 /* RuntimeErrorCode.RECURSIVE_APPLICATION_REF_TICK */, errorMessage);
        }
        try {
            this._runningTick = true;
            for (let view of this._views) {
                view.detectChanges();
            }
            if (typeof ngDevMode === 'undefined' || ngDevMode) {
                for (let view of this._views) {
                    view.checkNoChanges();
                }
            }
        }
        catch (e) {
            // Attention: Don't rethrow as it could cancel subscriptions to Observables!
            this._zone.runOutsideAngular(() => this._exceptionHandler.handleError(e));
        }
        finally {
            this._runningTick = false;
        }
    }

}
ログイン後にコピー

広い解釈では、この ApplicationRef は Angular アプリケーション全体のインスタンスです。コンストラクターでは、zone (ゾーン ライブラリ) onMicrotaskEmpty (名前から察するにマイクロタスクをクリアする科目です) サブスクライブしました。サブスクリプションでは、tick() が呼び出されます。tick では何が行われるのでしょうか?

感想: 前回、コンストラクター内でサブスクライブしない方が良いと言いましたが、なぜここでこれほど不規則になるのでしょうか。

もちろんそうではありません。前回は、Angular コンポーネントのどの部分を constructor に配置する必要があり、どの部分を ngOnInit に配置する必要があるかについて説明しました。ただし、ここでは ApplicationRef はサービスであるため、初期化コードは constructor にのみ配置できます。

tick 関数では、tick 関数が実行中であることが判明した場合、これはアプリケーション全体のインスタンスであり、再帰的に呼び出すことができないため、例外がスローされます。次に、すべてのビューを走査し、各ビューで detectChanges() が実行され、変更検出が実行されます。変更検出については後で詳しく説明します。その直後、devMode の場合、すべてのビューが再度走査され、各ビューが checkNoChanges() を実行して変更があるかどうかを確認します。変更がある場合は、エラーがスローされます ( Thisこの問題については後で詳しく説明します)。ここでは をスキップしてください)。

さて、これで更新方法がわかりました。つまり、ApplicationReftick メソッドを呼び出すことです。

import { Component, ViewChild, ElementRef, ApplicationRef } from '@angular/core';
@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.scss']
})
export class AppComponent  {
  name = 'Empty';

  @ViewChild('textContainer') textContainer: ElementRef = {} as any;

  constructor(private app: ApplicationRef){}

  normalClick(): void {
    this.name = 'Hello Angular';

    console.log(this.textContainer.nativeElement.innerText);

    this.app.tick();
  }
}
ログイン後にコピー

案の定、ビューは正常に更新できます。

簡単に整理しましょう。DOM の更新は tick() のトリガーに依存しています。zone.js は、開発者がこの操作を手動でトリガーすることを回避するのに役立ちます。さて、これでzone.jsを有効にすることができます。

それでは、変化検出とは何でしょうか?次回の記事もお楽しみに。

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

以上がAngular 変更検出における DOM 更新メカニズムの簡単な分析の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。

ホットAIツール

Undresser.AI Undress

Undresser.AI Undress

リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover

AI Clothes Remover

写真から衣服を削除するオンライン AI ツール。

Undress AI Tool

Undress AI Tool

脱衣画像を無料で

Clothoff.io

Clothoff.io

AI衣類リムーバー

AI Hentai Generator

AI Hentai Generator

AIヘンタイを無料で生成します。

ホットツール

メモ帳++7.3.1

メモ帳++7.3.1

使いやすく無料のコードエディター

SublimeText3 中国語版

SublimeText3 中国語版

中国語版、とても使いやすい

ゼンドスタジオ 13.0.1

ゼンドスタジオ 13.0.1

強力な PHP 統合開発環境

ドリームウィーバー CS6

ドリームウィーバー CS6

ビジュアル Web 開発ツール

SublimeText3 Mac版

SublimeText3 Mac版

神レベルのコード編集ソフト(SublimeText3)

Nodeのメモリ制御に関する記事 Nodeのメモリ制御に関する記事 Apr 26, 2023 pm 05:37 PM

ノンブロッキングおよびイベント駆動に基づいて構築されたノード サービスには、メモリ消費量が少ないという利点があり、大量のネットワーク リクエストの処理に非常に適しています。大量のリクエストを前提として、「メモリ制御」に関する問題を考慮する必要があります。 1. V8 のガベージ コレクション メカニズムとメモリ制限 Js はガベージ コレクション マシンによって制御されます

Vue3 で単体テストを作成する方法を調べる Vue3 で単体テストを作成する方法を調べる Apr 25, 2023 pm 07:41 PM

Vue.js は、今日のフロントエンド開発において非常に人気のあるフレームワークとなっています。 Vue.js が進化し続けるにつれて、単体テストの重要性がますます高まっています。今日は、Vue.js 3 で単体テストを作成する方法を検討し、いくつかのベスト プラクティスと一般的な問題と解決策を提供します。

Node の File モジュールについて詳しく説明しましょう Node の File モジュールについて詳しく説明しましょう Apr 24, 2023 pm 05:49 PM

ファイル モジュールは、ファイルの読み取り/書き込み/開く/閉じる/削除の追加など、基礎となるファイル操作をカプセル化したものです。ファイル モジュールの最大の特徴は、すべてのメソッドが **同期** と ** の 2 つのバージョンを提供することです。 asynchronous**、sync サフィックスが付いているメソッドはすべて同期メソッドであり、持たないメソッドはすべて異種メソッドです。

PHP と Vue: フロントエンド開発ツールの完璧な組み合わせ PHP と Vue: フロントエンド開発ツールの完璧な組み合わせ Mar 16, 2024 pm 12:09 PM

PHP と Vue: フロントエンド開発ツールの完璧な組み合わせ 今日のインターネットの急速な発展の時代において、フロントエンド開発はますます重要になっています。 Web サイトやアプリケーションのエクスペリエンスに対するユーザーの要求がますます高まっているため、フロントエンド開発者は、より効率的で柔軟なツールを使用して、応答性の高いインタラクティブなインターフェイスを作成する必要があります。フロントエンド開発の分野における 2 つの重要なテクノロジーである PHP と Vue.js は、組み合わせることで完璧なツールと見なされます。この記事では、PHP と Vue の組み合わせと、読者がこれら 2 つをよりよく理解し、適用できるようにするための詳細なコード例について説明します。

クロスドメインの問題を解決するにはどうすればよいですか?一般的なソリューションの簡単な分析 クロスドメインの問題を解決するにはどうすればよいですか?一般的なソリューションの簡単な分析 Apr 25, 2023 pm 07:57 PM

クロスドメインは開発においてよく遭遇するシナリオであり、インタビューでもよく議論される問題でもあります。一般的なクロスドメイン ソリューションとその背後にある原則を習得すると、開発効率が向上するだけでなく、面接でのパフォーマンスも向上します。

フロントエンドの面接官からよく聞かれる質問 フロントエンドの面接官からよく聞かれる質問 Mar 19, 2024 pm 02:24 PM

フロントエンド開発のインタビューでは、HTML/CSS の基本、JavaScript の基本、フレームワークとライブラリ、プロジェクトの経験、アルゴリズムとデータ構造、パフォーマンスの最適化、クロスドメイン リクエスト、フロントエンド エンジニアリング、デザインパターン、新しいテクノロジーとトレンド。面接官の質問は、候補者の技術スキル、プロジェクトの経験、業界のトレンドの理解を評価するように設計されています。したがって、候補者はこれらの分野で自分の能力と専門知識を証明するために十分な準備をしておく必要があります。

ノードのバッファーについて詳しく見る ノードのバッファーについて詳しく見る Apr 25, 2023 pm 07:49 PM

当初、JS はブラウザ側でのみ動作していたため、Unicode でエンコードされた文字列の処理は簡単でしたが、バイナリ文字列や非 Unicode エンコード文字列の処理は困難でした。バイナリは、コンピュータのビデオ/オーディオ/プログラム/ネットワーク パッケージの最低レベルのデータ形式です。

フロントエンド開発に Go 言語を使用するにはどうすればよいですか? フロントエンド開発に Go 言語を使用するにはどうすればよいですか? Jun 10, 2023 pm 05:00 PM

インターネット技術の発展に伴い、フロントエンド開発の重要性がますます高まっています。特にモバイル デバイスの人気により、効率的で安定しており、安全で保守が容易なフロントエンド開発テクノロジーが必要です。 Go 言語は、急速に発展しているプログラミング言語として、ますます多くの開発者によって使用されています。では、フロントエンド開発に Go 言語を使用することは可能でしょうか?次に、この記事ではフロントエンド開発にGo言語を使用する方法を詳しく説明します。まずはフロントエンド開発にGo言語が使われる理由を見てみましょう。多くの人は Go 言語は

See all articles