source

markForCheck()와 detectChanges()의 차이점은 무엇입니까?

ittop 2023. 5. 27. 11:57
반응형

markForCheck()와 detectChanges()의 차이점은 무엇입니까?

사이의 차이점은 무엇입니까?ChangeDetectorRef.markForCheck()그리고.ChangeDetectorRef.detectChanges()?

저는 SO에 대한 정보만 찾았습니다.NgZone.run()하지만 이 두 기능 사이에는 없습니다.

문서에 대한 참조만 포함된 답변의 경우, 다른 시나리오보다 하나를 선택할 수 있는 몇 가지 실제 시나리오를 설명하십시오.

변경 사항 탐지() : void

변경 디텍터와 하위 디텍터를 확인합니다.

즉, 모델(클래스) 내부의 내용이 변경되었지만 뷰를 반영하지 않은 경우 Angular에 통지하여 해당 변경 사항을 감지하고(로컬 변경 사항 감지) 뷰를 업데이트해야 할 수 있습니다.

가능한 시나리오는 다음과 같습니다.

1 - 변경 검출기가 뷰에서 분리됩니다(분리 참조).

2- 업데이트가 발생했지만 Angular Zone 내부에 있지 않아 Angular는 이에 대해 알지 못합니다.

예를 들어 타사 함수가 모델을 업데이트한 후 보기를 업데이트하려는 경우와 같습니다.

 someFunctionThatIsRunByAThirdPartyCode(){
     yourModel.text = "new text";
 }

이 코드는 Angular's zone(아마도) 밖에 있으므로 변경 사항을 감지하고 보기를 업데이트해야 할 가능성이 높습니다.

 myFunction(){
   someFunctionThatIsRunByAThirdPartyCode();

   // Let's detect the changes that above function made to the model which Angular is not aware of.
    this.cd.detectChanges();
 }

참고:

위의 작업을 수행할 수 있는 다른 방법이 있습니다. 즉, 각도 변경 주기 내에 변경 사항을 적용할 수 있는 다른 방법이 있습니다.

이 서드 파티 함수를 zone.run 안에 넣을 수 있습니다.

 myFunction(){
   this.zone.run(this.someFunctionThatIsRunByAThirdPartyCode);
 }

setTimeout 안에서 함수를 래핑할 수 있습니다.

myFunction(){
   setTimeout(this.someFunctionThatIsRunByAThirdPartyCode,0);
 }

3- 모델을 업데이트한 후에도change detection cycle완료되었습니다. 이 경우 다음과 같은 무서운 오류가 발생합니다.

"확인 후 식이 변경되었습니다.";

이것은 일반적으로 (Angular2 언어에서) 다음을 의미합니다.

제가 수락한 방법(이벤트, XHR 요청, setTimeout 및 ...) 중 하나로 인해 귀하의 모델이 변경된 것을 보고 변경 감지를 실행하여 귀하의 보기를 업데이트하고 완료했습니다.하지만 그때 당신의 코드에 모델을 다시 업데이트하는 다른 기능이 있었고 Angular와 같은 더러운 검사가 없기 때문에 나는 내 변경 감지를 다시 실행하고 싶지 않습니다.JS 더 이상 :D 그리고 우리는 단방향 데이터 흐름을 사용해야 합니다!

당신은 분명히 이 오류를 만나게 될 것입니다.

몇 가지 해결 방법:

1 - 적절한 방법 : 업데이트가 변경 감지 주기 내에 있는지 확인합니다(Angular2 업데이트는 한 번 발생하는 한 방향 흐름이며, 그 이후 모델을 업데이트하지 말고 코드를 더 나은 위치/시간으로 이동하십시오).

2 - Lazy way: 업데이트 후 detectChanges()를 실행하여 Angular2를 행복하게 만드는 것은 분명 최선의 방법은 아니지만, 가능한 시나리오가 무엇인지 물어보셨듯이, 이것은 그 중 하나입니다.

이런 식으로 말씀하시는 겁니다. 변경 감지를 실행하신 것은 진심으로 알고 있지만, 확인을 마친 후 즉시 업데이트해야 하는 사항이 있었기 때문에 다시 한 번 확인해 주시기 바랍니다.

- 를 3 - 코를a 습니다에 .setTimeout, 냐면왜setTimeout되며 "는 " 영별로적실다니행됩어되역"를 합니다.detectChanges완성된 후에


문서에서

markForCheck() : void

모든 ChangeDetection Strategy 상위 항목을 선택하도록 표시합니다.

구성 요소의 ChangeDetection Strategy가 OnPush일 때 주로 필요합니다.

OnPush 자체는 다음 중 하나가 발생한 경우에만 변경 감지를 실행합니다.

1 - 구성 요소의 @input 중 하나가 새 값으로 완전히 바뀌었거나, @Input 속성의 참조가 완전히 변경된 경우 간단히 입력합니다.

따라서 구성 요소의 ChangeDetection Strategy가 OnPush인 경우 다음과 같이 처리됩니다.

   var obj = {
     name:'Milad'
   };

그런 다음 다음과 같이 업데이트/변형합니다.

  obj.name = "a new name";

이렇게 하면 개체 참조가 업데이트되지 않으므로 변경 감지가 실행되지 않으므로 보기에 업데이트/변조가 반영되지 않습니다.

이 경우 Angular에 수동으로 지시하여 보기를 확인하고 업데이트해야 합니다(Mark For Check).

그래서 만약 당신이 이렇게 했다면:

  obj.name = "a new name";

이 작업을 수행해야 합니다.

  this.cd.markForCheck();

대신 아래에서는 변경 탐지가 실행됩니다.

    obj = {
      name:"a new name"
    };

Obj로 한 것입니다.{};

2 - 딸깍 소리 등 이벤트가 발생했거나 하위 구성 요소에서 이벤트가 발생했습니다.

다음과 같은 이벤트:

  • 클릭
  • 키업
  • 구독 이벤트
  • 기타.

간단히 말해서:

  • 사용하다detectChanges()각도가 실행된 후 모델을 업데이트한 경우 변경 사항이 감지되거나 업데이트가 각도가 지정되지 않은 경우

  • 사용하다markForCheck() OnPush를 에는 OnPush를 사용합니다.ChangeDetectionStrategy일부 데이터를 변경하거나 setTimeout 내에서 모델을 업데이트했습니다.

둘 사이의 가장 큰 차이점은detectChanges()는 변경 반면, 실로변 트하 는거 동안리 탐markForCheck()변경 탐지를 트리거하지 않습니다.

변경 사항 탐지

구성 대한 하는 데 됩니다.detectChanges()현재 구성 요소와 모든 하위 구성 요소에 대해 변경 탐지가 실행됩니다.Angular는 루트 구성 요소 트리에 대한 참조를 유지합니다.ApplicationRef그리고 비동기 작업이 발생하면 래퍼 메서드를 통해 이 루트 구성 요소에 대한 변경 탐지를 트리거합니다.tick():

@Injectable()
export class ApplicationRef_ extends ApplicationRef {
  ...
  tick(): void {
    if (this._runningTick) {
      throw new Error('ApplicationRef.tick is called recursively');
    }

    const scope = ApplicationRef_._tickScope();
    try {
      this._runningTick = true;
      this._views.forEach((view) => view.detectChanges()); <------------------

view루트 구성 요소 보기입니다.부트스트래핑 여러 구성 요소의 의미에서 설명한 것처럼 루트 구성 요소가 여러 개 있을 수 있습니다.

@milad는 변경 탐지를 수동으로 트리거해야 하는 이유를 설명했습니다.

확인 표시

제가 말씀드렸듯이, 이 사람은 전혀 변화를 감지하지 않습니다. 구성 요소로 를 재현구요소루구요위이쪽로으동보여다상업기로 합니다.ChecksEnabled소스 코드는 다음과 같습니다.

export function markParentViewsForCheck(view: ViewData) {
  let currView: ViewData|null = view;
  while (currView) {
    if (currView.def.flags & ViewFlags.OnPush) {
      currView.state |= ViewState.ChecksEnabled;  <-----------------
    }
    currView = currView.viewContainerParent || currView.parent;
  }
}

구성 요소에 대한 실제 변경 감지는 예약되지 않지만 향후 발생할 경우(현재 또는 다음 CD 사이클의 일부로) 상위 구성 요소 보기에 변경 감지기가 분리된 경우에도 확인됩니다.는 다을사변디분리수있습다니를 할 수 .cd.detach() 또는를지여하를 OnPush변경 감지 전략.모든 기본 이벤트 처리기는 모든 상위 구성요소 보기를 확인 표시합니다.

은 이접법종사다니용됩에서 됩니다.ngDoCheck라이프 사이클 훅구성 요소가 검사 중이라고 생각되는 경우 - 이 기사를 읽어 보십시오.

자세한 내용은 각도의 변경 탐지에 대해 알아야모든 내용을 참조하십시오.

markForCheck()와 detectChanges()의 차이를 설명하기 위해 4분짜리 스크린캐스트를 만들었습니다. - https://www.youtube.com/watch?v=OcphK_aEd7I

여기에 이미지 설명 입력

cd.detectChanges()현재 구성 요소에서 하위 구성 요소까지 변경 탐지를 즉시 실행합니다.

cd.markForCheck()변경 탐지를 실행하지 않고 변경 탐지를 실행해야 하는 상위 항목으로 표시합니다.다음 번에 변경 탐지가 아무 곳에서나 실행되면 표시된 구성 요소에 대해서도 실행됩니다.

  • 변경 탐지를 사용하는 횟수를 줄이려는 경우cd.markForCheck()변경사항은 여러 구성요소에 영향을 미치며 변경사항 탐지가 호출되는 경우가 많습니다.기본적으로 말씀하시는 것은, 이 구성 요소가 업데이트될 때 업데이트되는지 확인하는 것입니다.(보기는 작성한 모든 프로젝트에서 즉시 업데이트되지만 모든 유닛 테스트에서는 업데이트되지 않습니다.)
  • 그 확신수없할다면.cd.detectChanges() 현재 변경 탐지를 실행하고 있지 않습니다. 사용cd.markForCheck().detectChanges()이 경우 오류가 발생합니다.이것은 아마도 Angular의 변경 탐지가 설계되었다는 가정에 반하는 작업인 조상 성분의 상태를 편집하려고 한다는 것을 의미합니다.
  • 작업을 에는 다른작수행전보동경업하우여는야해를 사용합니다.detectChanges().markForCheck()시간 내에 보기를 업데이트하지 못할 수 있습니다.를 들어,에 영향을 . 를 들어 으로 장치테는영미칩 예를 들어 수동으로 호출해야 할 수 있습니다.fixture.detectChanges()앱 자체에 그것이 필요하지 않았을 때.
  • ▁by▁▁get▁▁if▁perform▁a다▁with있▁in▁may니습▁than▁state▁the수▁componentants▁a후▁you를 사용하여 성능을 향상시킬 수 있습니다.detectChanges()구성 요소의 조상에 대한 변경 탐지를 불필요하게 실행하지 않기 때문입니다.

가장 큰 차이 표시 ForCheck는 현재 구성 요소의 바인딩을 확인하고 하위 보기에서 DoCheck()와 같은 일부 생명원 후크를 호출하지 않지만 detectChange()는 호출합니다!

언급URL : https://stackoverflow.com/questions/41364386/whats-the-difference-between-markforcheck-and-detectchanges

반응형