변화 검측: (각도) 영역 진입!

8689 단어 angulartodayilearned
한 구성 요소의 이벤트 연결이 다른 구성 요소의 표시 오류를 초래할 수 있다는 것을 누가 알았습니까?정확한 위치에서 NgZone 문제를 해결하는 방법을 보여주기 전에 우리는 이 문제를 설명할 것이다.

장면 설정


우리 프로그램에는 사용자의 선택에 따라 데이터를 표시할 수 있는 도표가 있습니다.워크플로우는 다음과 같습니다.
  • 사용자가 드롭다운 목록에서 선택합니다.
  • 드롭다운 메뉴를 닫으면 선택 메시지가 표시됩니다.
  • api 호출을 터치하여 데이터를 되돌려줍니다.
  • 차트를 업데이트하여 데이터를 표시합니다.
  • 그러나 이번 주에 변경을 한 후에api 호출은 되돌아오지만 도표는 업데이트되지 않습니다.사용자와 페이지가 상호작용하기 전에 업데이트하지 않습니다.분명히 이것은 나쁜 사용자 체험이다.

    스티븐 쿠퍼
    @ 쿠퍼드프

    응, CPU 소모 setinterval을 복구하는 데 필요한 변화 검출 문제를 발견했어.사실이 증명하듯이setinterval의 부작용은 템플릿이 업데이트되는 것을 확보하는 것입니다!😢 이제 진짜 문제를 찾아내야...
    18:2020년 1월 23일 오후 4시

    관찰할 수 있는 트리거, 그러나 템플릿이 업데이트되지 않았습니다.

    setInterval"파이프를 관찰하고 데이터를 기록하면 업데이트된 데이터가 도착하고 있음을 쉽게 확인할 수 있습니다ChartComponent.
    chartData$ = this.data.pipe(
        tap(data => console.log("Data updated", data)
    );
    
    그렇다면, 왜 내 템플릿의 비동기 파이프는 도표를 업데이트하지 않았습니까?사용자가 페이지와 상호작용을 할 때, 왜 데이터가 갑자기 나타났습니까?
    <chart [data]="chartData$ | async"></chart>
    
    이런 상황에 부닥칠 때마다 변화 검출 문제가 있다는 것을 확신할 수 있다.이 경우 Angular는 데이터 업데이트 후 변경 검사 주기를 실행할 수 없습니다.근데 왜!?

    NgZones 회사


    만약 네가 익숙하지 않다면 먼저 읽어볼 만하다.한 마디로 하면 비동기식 작업은 Angular의 변경 탐지 영역 내부나 외부에서 실행될 수 있습니다.업데이트 지연은 차트 업데이트 이벤트가 Angular의 영역 밖에서 실행되고 있음을 나타냅니다.그러나, 우리 tapChartComponent 참조가 없습니다. 보통 Angular의 영역 밖에서 작업을 명확하게 실행해야 합니까?

    각도 분할 모두 원본 사건에 관한 것이다


    나는 데이터 파이프의 끝을 보지 말고 데이터 파이프의 시작을 봐야 한다는 것을 발견하는 데 시간이 좀 걸렸다.특히 업데이트를 시작하는 활동에서
    Angular 영역 외부에서 시작된 모든 이벤트는 변경 테스트를 트리거하지 않고 외부에서 실행됩니다.변경 검사가 없다는 것은 템플릿이 업데이트되지 않았다는 것을 의미합니다.이것은 때때로 이지만, 우리는 여기서 토론하지 않는다.
    만약api 호출, NgRx 효과, NgRx 조작을 통해 도표 업데이트를 하단 출력 이벤트로 거슬러 올라가고 마지막으로 구성 요소 내의 이벤트 이벤트로 거슬러 올라가면 다음과 같은 코드를 발견할 수 있습니다.
    @Component({...})
    export class DropdownComponent implements OnInit {
    
        @Output()
        updateSelection = new EventEmitter<any>();
    
        ngOnInit(){
            $('#dropdown').on('hidden.bs.dropdown', () => {
                this.updateSelection.emit(this.selections);
            });
        }
    }
    

    원하는 성능 jQuery 이벤트 처리 프로그램


    이 코드는 jQuery를 사용하여 아래 목록을 안내하는 을 감시합니다.이렇게 하면 드롭다운 메뉴가 닫힐 때 이벤트를 트리거할 수 있습니다.주의해야 할 관건은 안내ngZone가 Angular의 영역 밖에서 촉발되는 것이다.비록 우리는 hidden.bs.dropdown @Output 를 사용했지만, 전체 이벤트 체인은 Angular의 영역 밖에서 실행된다.
    이것은 이 사건의 어떠한 부작용도 우리의 템플릿에 반영되지 않는다는 것을 의미한다.이것이 바로 우리가 도표를 업데이트하지 않은 상황에서 본 상황이다.다른 이벤트가 변화 감지 주기를 촉발하여 도표가 이 시간에 업데이트되면 데이터가'갑자기'나타날 것이다.

    이벤트 숨기기 NgZone을 사용하여 문제 해결


    이 문제를 해결하기 위해서 우리는 Angular가 이 사건을 의식하도록 해야 한다.우리는 EventEmitterEventEmitter 방법에 포장함으로써 이 점을 실현한다. 아래와 같다.
    import { NgZone } from '@angular/core';
    
        constructor(private ngZone: NgZone) {}
    
        ngOnInit(){
            $('#dropdown').on('hidden.bs.dropdown', () => {
                this.ngZone.run(() => {
                    // Bring event back inside Angular's zone
                    this.updateSelection.emit(this.selections);
                });
            });
        }
    }
    
    이것은 이벤트가 현재 Angular에서 추적되고 변경 검사가 완료되면 실행된다는 것을 의미합니다!이 복구는 ngZone.run() 에 적용되었기 때문에 원본 이벤트에서 파생된 모든 후속 이벤트도 검사합니다.NgRx 동작과 효과를 사용할 때 중요합니다!

    잘못된 방법으로 ChartComponent 수정


    내가 이 문제를 해결하는 첫 번째 방법은 나의 DropdownComponent 중에서 사용하는 것이다.비록 이것은 도표를 복구했지만, 우리는 여전히 일치하지 않을 위험이 있다.
    예를 들어api 호출이 실패했을 때, 사용자에게 오류 메시지를 표시합니다.this.ngZone.run() 에서만 수정된 경우 다음 체크 주기를 변경하기 전까지는 이 오류 메시지가 표시되지 않습니다.우리는 ChartComponent 에서 같은 복구를 진행할 수 있지만, 현재 우리의 코드는 엉망진창이다. 우리가 이 복구를 얼마나 더 응용해야 할지 누가 알겠는가.
    우리의 예에서 가능한 한 빨리 사건을 Angular 구역으로 가져오는 것이 중요하다.그렇지 않으면 이 ChartComponent 를 사용할 때마다 복구를 반복해야 합니다.

    왜 나는 이전에 이 문제를 알아차리지 못했습니까?


    응용 프로그램의 다른 부분에서 CPU 집약형ErrorComponent을 삭제할 때 이 오류가 발생했습니다.사실은 DropdownComponent, setInterval이 자동적으로 Angular 구역 내의 사건을 촉발하여 변화 검측을 초래한 것으로 증명되었다.구간이 zone.js 로 설정되어 있기 때문에, 우리의 도표는 setInterval 시간이 지나기 때문에, 우리는 이전에 이 점을 주의하지 못했다.우리는 잠재적인 하단 문제를 복구할 뿐만 아니라 성능도 향상시켰다!

    총결산


    Angular 영역 밖에서 발생하는 이벤트를 가리키기 때문에 템플릿 업데이트가 지연되지 않도록 주의하십시오.그 다음으로 루트의 원인을 이해하기 전에 복구를 서둘러 적용하지 마라. 특히 변경 검측과 관련이 있을 때.증명하기 위해서, 다른 시간에 빠른 복구가 나의 최선의 선택이 아니라는 것을 보십시오.


    변경 검사: 시간 초과 설정 ()을 사용할 때 최선의 선택이 아닙니다. 스티븐 쿠퍼・ 2019년 11월 4일・ 5분 읽기 # 각도 #오늘 배웠어요 HostListener 관련 고려 사항


    만약 내가 500ms를 사용할 수 있다면, Isaac Mann과 Wes Grimes가 위에서 건의한 바와 같이 안내 이벤트를 포착할 수 있다면, 사용할 필요가 없다500ms.그러나 라인에서 설명한 바와 같이 나는 이 점을 실현할 수 없다.

    좋은 웹페이지 즐겨찾기