나는 이것에 대해 처음으로 질문하지는 않지만 이전 질문에서 답을 찾을 수 없다는 것을 알고 있습니다. 나는 이것을 하나의 구성 요소로 가지고 있습니다.
<div class="col-sm-5">
<laps
[lapsData]="rawLapsData"
[selectedTps]="selectedTps"
(lapsHandler)="lapsHandler($event)">
</laps>
</div>
<map
[lapsData]="rawLapsData"
class="col-sm-7">
</map>
컨트롤러 rawLapsdata
에서 때때로 변경됩니다.
에서 laps
, 데이터는 표 형식으로 HTML로서 출력된다. 변경 될 때마다 rawLapsdata
변경됩니다.
내 map
구성 요소의 요구에 사용하는 ngOnChanges
구글지도에 마커를 다시 그리기 트리거로. 문제는 rawLapsData
부모 가 변경 될 때 ngOnChanges가 실행되지 않는다는 것 입니다. 어떡해?
import {Component, Input, OnInit, OnChanges, SimpleChange} from 'angular2/core';
@Component({
selector: 'map',
templateUrl: './components/edMap/edMap.html',
styleUrls: ['./components/edMap/edMap.css']
})
export class MapCmp implements OnInit, OnChanges {
@Input() lapsData: any;
map: google.maps.Map;
ngOnInit() {
...
}
ngOnChanges(changes: { [propName: string]: SimpleChange }) {
console.log('ngOnChanges = ', changes['lapsData']);
if (this.map) this.drawMarkers();
}
업데이트 : ngOnChanges가 작동하지 않지만 lapsData가 업데이트되는 것처럼 보입니다. ngInit에는 줌 변경을위한 이벤트 리스너가 있으며this.drawmarkers
. 줌을 변경하면 실제로 마커가 변경되는 것을 볼 수 있습니다. 따라서 유일한 문제는 입력 데이터가 변경 될 때 알림을받지 못한다는 것입니다.
부모님에게는이 줄이 있습니다. 변경 사항은 랩에는 반영되지만 맵에는 반영되지 않습니다.
this.rawLapsData = deletePoints(this.rawLapsData, this.selectedTps);
그리고 this.rawLapsData
그 자체가 큰 json 객체의 중간을 가리키는 포인터입니다.
this.rawLapsData = this.main.data.TrainingCenterDatabase.Activities[0].Activity[0].Lap;
답변
rawLapsData
배열의 내용을 수정하더라도 (예 : 항목 추가, 항목 제거, 항목 변경)에도 동일한 배열을 계속 가리 킵니다.
변경 감지 중에 Angular는 구성 요소의 입력 속성에서 변경 사항을 검사 할 때 (필수적으로) ===
더티 검사에 사용합니다. 배열의 경우 이는 배열 참조 (전용)가 더티 검사됨을 의미합니다. 때문에 rawLapsData
배열 참조는 변경되지 않고, ngOnChanges()
호출되지 않을 것이다.
두 가지 가능한 솔루션을 생각할 수 있습니다.
-
ngDoCheck()
배열 내용이 변경되었는지 확인하기 위해 자체 변경 감지 논리를 구현 하고 수행하십시오. (Lifecycle Hooks 문서에는 예제가 있습니다.) -
rawLapsData
배열 내용을 변경할 때마다 새 배열을 할당하십시오 . 그러면ngOnChanges()
배열 (참조)이 변경으로 표시되므로 호출됩니다.
당신의 대답에서, 당신은 다른 해결책을 생각해 냈습니다.
OP에 대한 의견을 반복합니다.
여전히
laps
변경 사항을 가져올 수 있는 방법을 보지 못했습니다 (확실히ngOnChanges()
자신 합니까?)map
.
- 에서
laps
구성 요소 코드 / 된 템플릿의 각 항목을 통해 루프lapsData
배열 및 표시 내용 때문에 표시되는 데이터의 각 부분에 각도 바인딩이있다. - Angular가 구성 요소의 입력 속성에 대한 변경 사항을 감지하지 않더라도 (
===
확인 사용 ) 여전히 기본적으로 모든 템플릿 바인딩을 더티 확인합니다. 이 중 하나라도 변경되면 Angular는 DOM을 업데이트합니다. 그것이 당신이보고있는 것입니다. maps
구성 요소는 가능성의에 해당 템플리트의 모든 바인딩이없는lapsData
입력 속성을, 맞죠? 그것은 차이점을 설명 할 것입니다.
참고로 lapsData
두 구성 요소와 rawLapsData
동일한 / 하나의 어레이에 대한 모든 포인트 부모 구성 요소이다. 따라서 Angular가 lapsData
입력 속성에 대한 (참조) 변경 사항을 인식하지 않더라도 구성 요소는 하나의 배열을 공유 / 참조하기 때문에 “get”/ 배열 내용 변경을 볼 수 있습니다. 기본 유형 (문자열, 숫자, 부울)에서와 같이 이러한 변경 사항을 전파하기 위해 Angular가 필요하지 않습니다. 그러나 기본 유형의 경우 값을 변경하면 항상 트리거됩니다 ngOnChanges()
. 이는 답변 / 솔루션에서 악용하는 것입니다.
아마 지금까지 알아 낸 것처럼 객체 입력 속성은 배열 입력 속성과 동일한 동작을 갖습니다.
답변
가장 깨끗한 접근 방식은 아니지만 값을 변경할 때마다 객체를 복제 할 수 있습니까?
rawLapsData = Object.assign({}, rawLapsData);
나는 당신 자신을 구현하는 것 ngDoCheck()
보다이 접근법을 선호 하지만 @ GünterZöchbauer와 같은 누군가가 차임 할 수 있다고 생각합니다 .
답변
배열의 경우 다음과 같이 할 수 있습니다.
에서 .ts
파일 (부모 요소) 여기서 당신은 당신을 업데이트 rawLapsData
이런 식으로 작업을 수행합니다
rawLapsData = somevalue; // change detection will not happen
해결책:
rawLapsData = {...somevalue}; //change detection will happen
및 ngOnChanges
하위 구성 요소에서 호출됩니다
답변
Mark Rajcok의 두 번째 솔루션 확장
배열 내용을 변경할 때마다 rawLapsData에 새 배열을 할당하십시오. 그러면 배열 (참조)이 변경으로 표시되므로 ngOnChanges ()가 호출됩니다.
다음과 같이 배열의 내용을 복제 할 수 있습니다.
rawLapsData = rawLapsData.slice(0);
나는 이것을 언급하고 있기 때문에
rawLapsData = Object.assign ({}, rawLapsData);
나를 위해 일하지 않았다. 이게 도움이 되길 바란다.
답변
데이터가 외부 라이브러리에서 온 경우 데이터 업데이트 명령문을에서 실행해야 할 수도 있습니다 zone.run(...)
. zone: NgZone
이것을 주입 하십시오. zone.run()
이미 외부 라이브러리의 인스턴스화를 실행할 수 있으면 zone.run()
나중에 필요하지 않을 수 있습니다 .
답변
사용은 ChangeDetectorRef.detectChanges()
당신이 (그것의 더러운 검사로 그리워 있음) 중첩 된 개체를 편집 할 때 변경 감지를 실행하는 각도를 알 수 있습니다.
답변
문제를 해결하기위한 2 가지 해결책이 있습니다
- 데이터 변경 여부
ngDoCheck
를 감지하는object
데 사용 - 상위 구성 요소에서
object
새 메모리 주소를 지정하십시오object = Object.create(object)
.