-
04 컴포넌트 상호작용 07앵귤러/03 템플릿&데이터 바인딩 2017. 8. 22. 21:54
부모컴포넌트와 자식컴포넌트는 서비스를 통해 의사 소통합니다.
부모 컴포넌트와 자식 컴포넌트는 인터페이스가 해당 패밀리 내에서 양방향 통신을 가능하게하는 서비스를 공유합니다.
서비스 인스턴스의 범위는 부모 컴포넌트와 그 자식 컴포넌트 입니다. 이 컴포넌트 하위 트리 외부의 컴포넌트는 서비스 또는 통신에 액세스 할 수 없습니다.
이 MissionService는 MissionControlComponent를 여러 개의 AstronautComponent 자식과 연결합니다.
component-interaction/src/app/mission.service.ts
import { Injectable } from '@angular/core';
import { Subject } from 'rxjs/Subject';
@Injectable()
export class MissionService {
// Observable string sources
private missionAnnouncedSource = new Subject<string>();
private missionConfirmedSource = new Subject<string>();
// Observable string streams
missionAnnounced$ = this.missionAnnouncedSource.asObservable();
missionConfirmed$ = this.missionConfirmedSource.asObservable();
// Service message commands
announceMission(mission: string) {
this.missionAnnouncedSource.next(mission);
}
confirmMission(astronaut: string) {
this.missionConfirmedSource.next(astronaut);
}
}
MissionControlComponent는 providers 메타 데이터 배열을 통해 자식과 공유하는 서비스의 인스턴스를 제공하고 생성자를 통해 그 인스턴스를 자신에게 주입합니다.
component-interaction/src/app/missioncontrol.component.ts
import { Component } from '@angular/core';
import { MissionService } from './mission.service';
@Component({
selector: 'mission-control',
template: `
<h2>Mission Control</h2>
<button (click)="announce()">Announce mission</button>
<my-astronaut *ngFor="let astronaut of astronauts"
[astronaut]="astronaut">
</my-astronaut>
<h3>History</h3>
<ul>
<li *ngFor="let event of history">{{event}}</li>
</ul>
`,
providers: [MissionService]
})
export class MissionControlComponent {
astronauts = ['Lovell', 'Swigert', 'Haise'];
history: string[] = [];
missions = ['Fly to the moon!',
'Fly to mars!',
'Fly to Vegas!'];
nextMission = 0;
constructor(private missionService: MissionService) {
missionService.missionConfirmed$.subscribe(
astronaut => {
this.history.push(`${astronaut} confirmed the mission`);
});
}
announce() {
let mission = this.missions[this.nextMission++];
this.missionService.announceMission(mission);
this.history.push(`Mission "${mission}" announced`);
if (this.nextMission >= this.missions.length) { this.nextMission = 0; }
}
}
AstronautComponent는 생성자에서 서비스를 주입합니다. 각 AstronautComponent는 MissionControlComponent의 자식이므로 부모의 서비스 인스턴스를 받습니다.
component-interaction/src/app/astronaut.component.ts
import { Component, Input, OnDestroy } from '@angular/core';
import { MissionService } from './mission.service';
import { Subscription } from 'rxjs/Subscription';
@Component({
selector: 'my-astronaut',
template: `
<p>
{{astronaut}}: <strong>{{mission}}</strong>
<button
(click)="confirm()"
[disabled]="!announced || confirmed">
Confirm
</button>
</p>
`
})
export class AstronautComponent implements OnDestroy {
@Input() astronaut: string;
mission = '<no mission announced>';
confirmed = false;
announced = false;
subscription: Subscription;
constructor(private missionService: MissionService) {
this.subscription = missionService.missionAnnounced$.subscribe(
mission => {
this.mission = mission;
this.announced = true;
this.confirmed = false;
});
}
confirm() {
this.confirmed = true;
this.missionService.confirmMission(this.astronaut);
}
ngOnDestroy() {
// prevent memory leak when component destroyed
this.subscription.unsubscribe();
}
}
이 예제는 AstronautComponent가 소멸 될 때 subscription과 unsubscribe()를 캡처합니다. 이것은 메모리 누출 보호 단계입니다. AstronautComponent의 수명이 앱 자체의 수명과 동일하기 때문에 이 앱에는 실제 위험은 없습니다. 좀더 복잡한 응용프로그램에서는 위험이 없는 것은 아닙니다.
부모컴포넌트가 MissionService의 수명을 제어하기 때문에 이 보호를 MissionControlComponent에 추가하지 마십시오.
히스토리 로그는 메시지가 부모 MissionControlComponent와 자식AstronautComponent 사이에 서비스를 통해서 양방향으로 이동 함을 보여줍니다.
'앵귤러 > 03 템플릿&데이터 바인딩' 카테고리의 다른 글
05 컴포넌트 스타일 02 (0) 2017.08.27 05 컴포넌트 스타일 01 (0) 2017.08.27 04 컴포넌트 상호작용 06 (0) 2017.08.22 04 컴포넌트 상호작용 05 (0) 2017.08.22 04 컴포넌트 상호작용 04 (0) 2017.08.22