Angular 시리즈 의 변화 검출 상세 설명(Change Detection)
쉽게 말 하면 변화 검출 은 Angular 가 보기 와 모델 사이 에 연 결 된 값 이 바 뀌 었 는 지,모델 에 연 결 된 값 이 바 뀌 었 는 지 확인 할 때 보기 로 동기 화 하 는 것 입 니 다.반대로 보기 에 연 결 된 값 이 바 뀌 었 는 지 감지 되면 해당 하 는 바 인 딩 함 수 를 되 돌려 줍 니 다.
어떤 상황 에서 변화 검 사 를 일 으 킬 수 있 습 니까?
요약 하면 다음 과 같은 몇 가지 상황 도 데 이 터 를 바 꿀 수 있다.
사용자 입력 조작,예 를 들 어 클릭,제출 등요청 서버 데이터(XHR)시간 이벤트,예 를 들 어 setTimeout,setInterval상기 세 가지 상황 은 모두 하나의 공통점 이 있다.즉,바 인 딩 값 이 바 뀌 는 사건 은 모두 비동기 적 으로 발생 한 것 이다.만약 이러한 비동기 적 인 사건 이 발생 할 때 Angular 프레임 워 크 에 알 릴 수 있다 면 Angular 프레임 워 크 는 신속하게 변 화 를 감지 할 수 있 을 것 이다.
왼쪽 에 실행 할 코드 를 표시 합 니 다.이 stack 은 자바 script 의 실행 스 택 을 표시 합 니 다.웹 Api 는 브 라 우 저 에서 제공 하 는 자바 script 의 API 입 니 다.TaskQueue 는 자바 script 에서 작업 대기 열 을 표시 합 니 다.자바 script 은 단일 스 레 드 이 고 비동기 작업 은 작업 대기 열 에서 실 행 됩 니 다.
구체 적 으로 말 하면 비동기 실행 체 제 는 다음 과 같다.
4.567917.모든 동기 화 작업 은 주 스 레 드 에서 실행 되 고 실행 스 택(execution context stack)을 형성 합 니 다
angular 2 변화 알림 가 져 오기
그렇다면 문제 가 생 겼 다.angular 2 는 데이터 가 바 뀌 었 다 는 것 을 어떻게 알 았 을 까?DOM 의 위 치 를 수정 해 야 하 는 지,정확 한 최소 범위 의 DOM 을 어떻게 알 았 을 까?맞아요.가능 한 한 작은 범위 에서 DOM 을 수정 하 세 요.왜냐하면 DOM 을 조작 하 는 것 은 성능 에 있어 서 사치품 이기 때 문 입 니 다.
AngularJS 에 서 는 코드$scope.$apply()또는$scope.$digest 가 촉발 되 었 으 며,Angular 는 ZoneJS 에 접속 하여 Angular 의 모든 비동기 이 벤트 를 감청 하 였 습 니 다.
존 제 이 스 는 어떻게 했 을까요?
사실 존 에 원숭이 패 치 라 는 게 있어 요.Zone.js 가 실 행 될 때 이 비동기 이벤트 에 대한 프 록 시 패 키 지 를 만 듭 니 다.즉,Zone.js 가 실 행 된 후 setTimeout,addEventListener 등 브 라 우 저 비동기 이 벤트 를 호출 할 때 원생 을 호출 하 는 방법 이 아니 라 원숭이 패 치 에 포 장 된 프 록 시 방법 입 니 다.에이전트 에 서 는 갈고리 함수 가 설정 되 어 있 습 니 다.이 갈고리 함수 들 을 통 해 비동기 작업 이 수행 하 는 문맥 에 편리 하 게 들 어 갈 수 있 습 니 다.
// Zone.js
function zoneAwareAddEventListener() {...}
function zoneAwareRemoveEventListener() {...}
function zoneAwarePromise() {...}
function patchTimeout() {...}
window.prototype.addEventListener=zoneAwareAddEventListener;
window.prototype.removeEventListener=zoneAwareRemoveEventListener;
window.prototype.promise = zoneAwarePromise;
window.prototype.setTimeout = patchTimeout;
변화 검출 과정Angular 의 핵심 은 구성 요소 화 입 니 다.구성 요소 의 끼 워 넣 기 는 최종 적 으로 구성 요소 트 리 를 만 들 수 있 습 니 다.Angular 의 변화 검 사 는 구성 요소 로 나 누 어 진행 할 수 있 습 니 다.모든 Component 는 하나의 changeDetector 에 대응 합 니 다.우 리 는 Component 에서 의존 주입 을 통 해 changeDetector 를 얻 을 수 있 습 니 다.그리고 우리 의 여러 Component 는 나무 구조의 조직 입 니 다.하나의 Component 가 하나의 changeDetector 에 대응 하기 때문에 changeDetector 간 에 똑 같은 나무 구조의 조직 입 니 다.
또한,Angular 의 데이터 흐름 은 부모 구성 요소 에서 하위 구성 요소 로 단 방향 으로 흐 릅 니 다.단 방향 데이터 흐름 은 효율 적 이 고 예측 가능 한 변화 검 측 을 보장 한다.부모 구성 요 소 를 검사 한 후에 도 하위 구성 요 소 는 부모 구성 요소 의 데 이 터 를 바 꾸 어 부모 구성 요 소 를 다시 검사 해 야 할 수 있 습 니 다.이것 은 추천 되 지 않 는 데이터 처리 방식 입 니 다.개발 모드 에서 Angular 는 2 차 검 사 를 진행 합 니 다.상기 상황 이 발생 하면 2 차 검 사 는 오류 가 발생 합 니 다.Expression Changed After It Has Been Checked Error.생산 환경 에 서 는 더러 운 검 사 를 한 번 만 한다.
이에 비해 AngularJS 는 양 방향 데이터 흐름 을 사용 하고 복잡 한 데이터 흐름 으로 인해 여러 번 검 사 를 해 야 하기 때문에 데이터 가 최종 적 으로 안정 적 인 추 세 를 보인다.이론 적 으로 데 이 터 는 영원히 불안정 할 수 있다.AngularJS 는 더러 운 검 사 를 10 회 이상 하면 프로그램 에 문제 가 있다 고 보고 검 사 를 하지 않 는 다 는 전략 을 내 놓 았 다.
변화 검출 정책
Angular 는 두 가지 변화 검출 전략 이 있 습 니 다.Default 는 Angular 의 기본 변화 검출 정책 입 니 다.즉,위 에서 언급 한 더러 운 검사 입 니 다.값 이 바 뀌 면 모두 부모 구성 요소 에서 모든 하위 구성 요소 로 검 사 를 합 니 다.또 다른 효율 적 인 변화 검출 방식:OnPush.OnPush 정책 은 입력 데이터(즉@Input)의 인용 이 바 뀌 거나 이벤트 가 발생 했 을 때 만 구성 요소 가 변화 검 사 를 하 는 것 입 니 다.
defalut 정책
main.component.ts
@Component({
selector: 'app-root',
template: `
<h1> </h1>
<p>{{ slogan }}</p>
<button type="button" (click)="changeStar()">
</button>
<button type="button" (click)="changeStarObject()">
</button>
<movie [title]="title" [star]="star"></movie>`,
})
export class AppComponent {
slogan: string = 'change detection';
title: string = 'default ';
star: Star = new Star(' ', ' ');
changeStar() {
this.star.firstName = ' ';
this.star.lastName = ' ';
}
changeStarObject() {
this.star = new Star(' ', ' ');
}
}
movie.component.ts
@Component({
selector: 'movie',
styles: ['div {border: 1px solid black}'],
template: `
<div>
<h3>{{ title }}</h3>
<p>
<label>Star:</label>
<span>{{star.firstName}} {{star.lastName}}</span>
</p>
</div>`,
})
export class MovieComponent {
@Input() title: string;
@Input() star;
}
위의 코드 에서 첫 번 째 단 추 를 누 르 면 스타 속성 을 바 꿀 때 slogan,title,star 세 가지 속성 을 차례로 검 측 합 니 다.이때 세 가지 속성 은 모두 변화 가 없습니다.star 는 변화 가 없 었 습 니 다.실질 적 으로 star 검 측 시 star 자체 의 인용 값 이 바 뀌 었 는 지 만 검 측 했 기 때 문 입 니 다.star 의 속성 값 을 바 꾸 면 star 자체 의 인용 을 바 꾸 지 않 았 습 니 다.그래서 변 함 이 없다.우리 가 두 번 째 단 추 를 눌 러 스타 의 대상 을 바 꾸 었 을 때 새로운 스타 가 생 겼 다.이때 변화 검 측 에서 스타 가 바 뀌 었 다 는 것 을 알 수 있다.
그리고 변 화 는 하위 구성 요소 에 들 어가 star.firstName 과 star.lastName 에 변화 가 생 겼 음 을 감지 하고 보 기 를 업데이트 합 니 다.
OnPush 정책
위의 코드 에 비해 movie.coponent.ts 의@component 에 만 코드 를 추가 하 였 습 니 다.
changeDetection:ChangeDetectionStrategy.OnPush
이 때 첫 번 째 단 추 를 눌 렀 을 때 스타 가 변 하지 않 았 음 을 알 수 있 습 니 다.ok,변 화 는 여기 서 끝 났 습 니 다.하위 구성 요소 에 들 어가 지 않 고 보기 가 변 하지 않 습 니 다.
두 번 째 단 추 를 누 르 면 star 에 변화 가 생 겼 음 을 감지 하고 하위 구성 요소 에 들 어 갔 을 때 star.firstName 과 star.lastName 에 변화 가 생 겼 음 을 감지 하고 보 기 를 업데이트 합 니 다.
따라서 OnPush 검 측 체 제 를 사 용 했 을 때 바 인 딩 값 의 속성 을 수정 할 때 바 인 딩 값 자체 의 인용 을 동시에 수정 하 는 지 확인 해 야 합 니 다.하지만 속성 치 를 바 꿔 야 할 때마다 new 에 새로운 대상 으로 가 는 것 은 귀 찮 습 니 다.immutable.js 는 가 질 만 한 가치 가 있 습 니 다!
변화 검출 대상 참조
변화 검출 대상 Change Detector Ref 를 참조 하여 변화 검출 을 수 동 으로 조작 할 수 있 습 니 다.구성 요소 에서 주입 에 의존 하 는 방식 으로 대상 을 가 져 올 수 있 습 니 다.
constructor(
private changeRef:ChangeDetectorRef
){}
변화 검출 대상 이 제공 하 는 방법 은 다음 과 같은 몇 가지 가 있다.구성 요소 에 이벤트 추가 입력 속성 변경
위 코드 movie.coponent.ts 에서 다음 과 같이 수정 합 니 다.
@Component({
selector: 'movie',
styles: ['div {border: 1px solid black}'],
template: `
<div>
<h3>{{ title }}</h3>
<p>
<button (click)="changeStar()"> </button>
<label>Star:</label>
<span>{{star.firstName}} {{star.lastName}}</span>
</p>
</div>`,
changeDetection:ChangeDetectionStrategy.OnPush
})
export class MovieComponent {
constructor(
private changeRef:ChangeDetectorRef
){}
@Input() title: string;
@Input() star;
changeStar(){
this.star.lastName = 'xjl';
}
}
이 때 단 추 를 누 르 면 이름 을 바 꿀 때 star 는 다음 과 같이 변 경 됩 니 다.![그림 설명][3]
두 번 째 는 위 에서 말 한 변화 검출 대상 의 markForCheck()방법 을 사용 하 는 것 이다.
ngOnInit() {
setInterval(() => {
this.star.lastName = 'xjl';
this.changeRef.markForCheck();
}, 1000);
}
Observable 속성 입력app.component.ts 수정
@Component({
selector: 'app-root',
template: `
<h1> </h1>
<p>{{ slogan }}</p>
<button type="button" (click)="changeStar()">
</button>
<button type="button" (click)="changeStarObject()">
</button>
<movie [title]="title" [star]="star" [addCount]="count"></movie>`,
})
export class AppComponent implements OnInit{
slogan: string = 'change detection';
title: string = 'OnPush ';
star: Star = new Star(' ', ' ');
count:Observable<any>;
ngOnInit(){
this.count = Observable.timer(0, 1000)
}
changeStar() {
this.star.firstName = ' ';
this.star.lastName = ' ';
}
changeStarObject() {
this.star = new Star(' ', ' ');
}
}
이때 MovieComponent 를 검 측 에 들 어가 게 하 는 두 가지 방법 이 있 는데 하 나 는 변화 검 측 대상 중의 markForCheck()방법 을 사용 하 는 것 이다.
ngOnInit() {
this.addCount.subscribe(() => {
this.count++;
this.changeRef.markForCheck();
})
다른 하 나 는 async pipe 파 이 프 를 사용 하 는 것 입 니 다.
@Component({
selector: 'movie',
styles: ['div {border: 1px solid black}'],
template: `
<div>
<h3>{{ title }}</h3>
<p>
<button (click)="changeStar()"> </button>
<label>Star:</label>
<span>{{star.firstName}} {{star.lastName}}</span>
</p>
<p>{{addCount | async}}</p>
</div>`,
changeDetection: ChangeDetectionStrategy.OnPush
})
이상 이 바로 본 고의 모든 내용 입 니 다.여러분 의 학습 에 도움 이 되 고 저 희 를 많이 응원 해 주 셨 으 면 좋 겠 습 니 다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
연말이므로 웹 앱을 만들었습니다.minmax 패널을 번갈아 가서 총 득점을 겨루는 게임이다. 선수는 좋아하는 위치에서 시작된다. 후손은 선수가 선택한 위치를 포함한 세로 일렬 중에서 패널을 선택한다. 다시 선수는 후손이 선택한 패널을 포함한 가로 ...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.