Analisis ringkas mekanisme kemas kini DOM dalam pengesanan perubahan sudut

青灯夜游
Lepaskan: 2022-12-12 20:21:15
ke hadapan
2562 orang telah melayarinya

Analisis ringkas mekanisme kemas kini DOM dalam pengesanan perubahan sudut

Pengesanan perubahan ialah bahagian penting Sudut, iaitu untuk mengekalkan penyegerakan antara model dan pandangan. Dalam proses pembangunan harian, kami tidak perlu mengetahui tentang pengesanan perubahan, kerana Angular membantu kami menyelesaikan bahagian kerja ini, membolehkan pembangun menumpukan lebih pada pelaksanaan perniagaan, meningkatkan kecekapan pembangunan dan pengalaman pembangunan. Tetapi jika anda ingin menggunakan rangka kerja secara mendalam, atau jika anda ingin menulis kod berprestasi tinggi dan bukannya hanya melaksanakan fungsi, anda mesti memahami pengesanan perubahan ini boleh membantu kami memahami dengan lebih baik rangka kerja, ralat nyahpepijat, meningkatkan prestasi, dsb. [Tutorial berkaitan yang disyorkan: "tutorial sudut"]

Mekanisme kemas kini DOM Angular

Mari kita lihat contoh kecil dahulu.

Apabila kami mengklik butang, atribut nama ditukar dan DOM dikemas kini secara automatik dengan nilai nama baharu.

Sekarang ada soalan Jika saya menukar nilai nama dan kemudian mengeluarkan innerText dalam DOM, apakah nilainya?

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);
  }
}
Salin selepas log masuk

Adakah anda menjawabnya dengan betul?

Jadi apa sebenarnya yang berlaku dalam dua keping kod ini?

Jika kami menggunakan JS asli untuk menulis kod ini, maka paparan pasti tidak akan berubah selepas mengklik butang, tetapi paparan berubah dalam Sudut, maka mengapa ia secara automatik mengemas kini kain Woolen? Ini tidak dapat dipisahkan daripada perpustakaan yang dipanggil zone.js Secara ringkasnya, ia melakukan beberapa pemprosesan peristiwa di mana nilai berubah Ini akan diterangkan secara terperinci dalam bahagian berikut.

Jika saya tidak mahu pustaka ini melakukan pemprosesan ini, Angular juga menyediakan kami cara untuk melumpuhkan zone.js.

Anda boleh melumpuhkan zone.js dalam main.ts.

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));
Salin selepas log masuk

Apabila kami melumpuhkan zone.js, paparan tidak dikemas kini. Pergi ke kod sumber untuk mencari kod yang berkaitan untuk kemas kini paparan.

 */
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;
        }
    }

}
Salin selepas log masuk

Untuk memberikan tafsiran kasar, ApplicationRef ini ialah contoh bagi keseluruhan aplikasi Angular Dalam pembina, zon (pustaka zon) onMicrotaskEmpty (Berdasarkan nama, ia adalah subjek yang membersihkan microtasks) Dilanggan. Dalam langganan, tick() dipanggil, kemudian apa yang dilakukan dalam tick?

Berfikir: Saya katakan kali terakhir bahawa adalah lebih baik untuk tidak melanggan pembina Mengapa ia sangat tidak teratur di sini?

Sudah tentu tidak kali terakhir kita bercakap tentang komponen Angular yang harus diletakkan dalam pembina dan yang harus diletakkan dalam ngOnInit. Tetapi di sini, ApplicationRef ialah perkhidmatan, jadi kod permulaan hanya boleh diletakkan dalam pembina.

Dalam fungsi tick, jika didapati bahawa fungsi tick sedang dilaksanakan, pengecualian akan dilemparkan kerana ini adalah contoh dari keseluruhan aplikasi dan tidak boleh dipanggil secara rekursif. Kemudian, semua pandangan dilalui, dan kemudian setiap paparan melaksanakan detectChanges(), iaitu, pengesanan perubahan dilakukan Apa itu pengesanan perubahan akan diterangkan secara terperinci kemudian. Kemudian, jika ia adalah devMode, rentas semua paparan sekali lagi dan setiap paparan melaksanakan checkNoChanges() untuk menyemak sama ada terdapat sebarang perubahan, ralat akan dilemparkan ( Isu ini akan dibincangkan secara terperinci kemudian) , langkau sekarang ).

Nah, sekarang kita tahu cara mengemas kininya, iaitu memanggil kaedah tandakan ApplicationRef.

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();
  }
}
Salin selepas log masuk

Sudah tentu, paparan boleh dikemas kini seperti biasa.

Mari kita semak secara ringkas kemas kini DOM bergantung pada pencetus tick() zone.js membantu pembangun mengelak daripada mencetuskan operasi ini secara manual. Okay, kini anda boleh mendayakan zone.js.

Jadi apakah pengesanan perubahan? Nantikan artikel seterusnya.

Untuk lebih banyak pengetahuan berkaitan pengaturcaraan, sila lawati: Pengajaran Pengaturcaraan! !

Atas ialah kandungan terperinci Analisis ringkas mekanisme kemas kini DOM dalam pengesanan perubahan sudut. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

sumber:juejin.cn
Kenyataan Laman Web ini
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn
Tutorial Popular
Lagi>
Muat turun terkini
Lagi>
kesan web
Kod sumber laman web
Bahan laman web
Templat hujung hadapan