목차
Angular의 DOM 업데이트 메커니즘
웹 프론트엔드 JS 튜토리얼 각도 변화 감지의 DOM 업데이트 메커니즘에 대한 간략한 분석

각도 변화 감지의 DOM 업데이트 메커니즘에 대한 간략한 분석

Dec 12, 2022 pm 07:44 PM
프런트 엔드 angular.js 변화 감지 DOM 업데이트 메커니즘

각도 변화 감지의 DOM 업데이트 메커니즘에 대한 간략한 분석

변경 감지는 Angular에서 매우 중요한 부분으로, 모델과 뷰 간의 동기화를 유지하는 것입니다. 일상적인 개발 프로세스에서는 변경 감지에 대해 알 필요가 없습니다. Angular는 작업의 이 부분을 완료하는 데 도움을 주어 개발자가 비즈니스 구현에 더 집중하고 개발 효율성과 개발 경험을 향상시킬 수 있기 때문입니다. 그러나 프레임워크를 심층적으로 사용하고 싶거나 단순히 함수를 구현하는 대신 고성능 코드를 작성하려면 변경 감지를 이해해야 합니다. 이를 통해 프레임워크를 더 잘 이해하고 오류를 디버그하며 성능을 향상할 수 있습니다. [추천 관련 튜토리얼: "angular Tutorial"]

Angular의 DOM 업데이트 메커니즘

먼저 작은 예를 살펴보겠습니다.

버튼을 클릭하면 name 속성이 변경되고 DOM이 자동으로 새 이름 값으로 업데이트됩니다.

이제 질문이 있습니다. 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);
  }
}
로그인 후 복사

정답하셨나요?

그렇다면 이 두 코드에서 정확히 무슨 일이 일어나는 걸까요?

네이티브 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()를 실행하여 변경 사항이 있는지 확인합니다. 변경 사항이 있으면 오류가 발생합니다(이 문제에 대해서는 나중에 자세히 설명하겠습니다. , 지금은 건너뛰세요) . 좋아, 이제 업데이트하는 방법을 알았습니다. 즉,

ApplicationRef

tick 메서드를 호출하는 것입니다.

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를 활성화할 수 있습니다. 그럼 변화 감지란 무엇인가요? 다음 기사를 계속 기대해 주세요.

더 많은 프로그래밍 관련 지식을 보려면

프로그래밍 교육

을 방문하세요! !

위 내용은 각도 변화 감지의 DOM 업데이트 메커니즘에 대한 간략한 분석의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 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 Hentai를 무료로 생성하십시오.

뜨거운 도구

메모장++7.3.1

메모장++7.3.1

사용하기 쉬운 무료 코드 편집기

SublimeText3 중국어 버전

SublimeText3 중국어 버전

중국어 버전, 사용하기 매우 쉽습니다.

스튜디오 13.0.1 보내기

스튜디오 13.0.1 보내기

강력한 PHP 통합 개발 환경

드림위버 CS6

드림위버 CS6

시각적 웹 개발 도구

SublimeText3 Mac 버전

SublimeText3 Mac 버전

신 수준의 코드 편집 소프트웨어(SublimeText3)

Node의 메모리 제어에 관한 기사 Node의 메모리 제어에 관한 기사 Apr 26, 2023 pm 05:37 PM

Non-Blocking, Event-Driven 기반으로 구축된 Node 서비스는 메모리 소모가 적다는 장점이 있으며, 대규모 네트워크 요청을 처리하는데 매우 적합합니다. 대규모 요청을 전제로 '메모리 제어'와 관련된 문제를 고려해야 합니다. 1. V8의 가비지 수집 메커니즘과 메모리 제한 Js는 가비지 수집 기계에 의해 제어됩니다.

Vue3에서 단위 테스트를 작성하는 방법 살펴보기 Vue3에서 단위 테스트를 작성하는 방법 살펴보기 Apr 25, 2023 pm 07:41 PM

Vue.js는 오늘날 프런트엔드 개발에서 매우 인기 있는 프레임워크가 되었습니다. Vue.js가 계속 발전함에 따라 단위 테스트는 점점 더 중요해지고 있습니다. 오늘은 Vue.js 3에서 단위 테스트를 작성하는 방법을 살펴보고 몇 가지 모범 사례와 일반적인 문제 및 솔루션을 제공하겠습니다.

Node의 파일 모듈에 대해 자세히 이야기해 보겠습니다. Node의 파일 모듈에 대해 자세히 이야기해 보겠습니다. Apr 24, 2023 pm 05:49 PM

파일 모듈은 파일 읽기/쓰기/열기/닫기/삭제 추가 등과 같은 기본 파일 작업을 캡슐화한 것입니다. 파일 모듈의 가장 큰 특징은 모든 메소드가 **동기** 및 ** 두 가지 버전을 제공한다는 것입니다. 비동기**, sync 접미사가 있는 메서드는 모두 동기화 메서드이고, 없는 메서드는 모두 이기종 메서드입니다.

PHP와 Vue: 프런트엔드 개발 도구의 완벽한 조합 PHP와 Vue: 프런트엔드 개발 도구의 완벽한 조합 Mar 16, 2024 pm 12:09 PM

PHP와 Vue: 프론트엔드 개발 도구의 완벽한 조합 오늘날 인터넷이 빠르게 발전하는 시대에 프론트엔드 개발은 점점 더 중요해지고 있습니다. 사용자가 웹 사이트 및 애플리케이션 경험에 대한 요구 사항이 점점 더 높아짐에 따라 프런트 엔드 개발자는 보다 효율적이고 유연한 도구를 사용하여 반응형 및 대화형 인터페이스를 만들어야 합니다. 프론트엔드 개발 분야의 두 가지 중요한 기술인 PHP와 Vue.js는 함께 사용하면 완벽한 도구라고 볼 수 있습니다. 이 기사에서는 독자가 이 두 가지를 더 잘 이해하고 적용할 수 있도록 PHP와 Vue의 조합과 자세한 코드 예제를 살펴보겠습니다.

도메인 간 문제를 해결하는 방법은 무엇입니까? 일반적인 솔루션에 대한 간략한 분석 도메인 간 문제를 해결하는 방법은 무엇입니까? 일반적인 솔루션에 대한 간략한 분석 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는 브라우저 측에서만 실행되었습니다. 유니코드로 인코딩된 문자열은 처리하기 쉬웠지만 바이너리 및 유니코드가 아닌 인코딩된 문자열을 처리하는 것은 어려웠습니다. 그리고 바이너리는 컴퓨터의 가장 낮은 데이터 형식인 비디오/오디오/프로그램/네트워크 패키지입니다.

프론트엔드 개발에 Go 언어를 사용하는 방법은 무엇입니까? 프론트엔드 개발에 Go 언어를 사용하는 방법은 무엇입니까? Jun 10, 2023 pm 05:00 PM

인터넷 기술이 발전하면서 프론트엔드 개발이 점점 더 중요해지고 있습니다. 특히 모바일 장치의 인기는 효율적이고 안정적이며 안전하고 유지 관리가 쉬운 프런트 엔드 개발 기술을 요구합니다. 빠르게 발전하는 프로그래밍 언어로서 Go 언어는 점점 더 많은 개발자가 사용하고 있습니다. 그렇다면 프론트엔드 개발에 Go 언어를 사용하는 것이 가능할까요? 다음으로 이 글에서는 프론트엔드 개발에 Go 언어를 사용하는 방법을 자세히 설명하겠습니다. 먼저 프론트엔드 개발에 Go 언어가 사용되는 이유를 살펴보겠습니다. 많은 사람들이 Go 언어가 언어라고 생각합니다.

See all articles