먼저 구성 요소 간의 관계를 이해해야합니다. 그런 다음 올바른 의사 소통 방법을 선택할 수 있습니다. 구성 요소 간 통신을 위해 실습에서 알고 사용하는 모든 방법을 설명하려고합니다.
구성 요소간에 어떤 종류의 관계가있을 수 있습니까?
1. 부모> 자녀
입력을 통한 데이터 공유
아마도 가장 일반적인 데이터 공유 방법 일 것입니다. @Input()
데코레이터를 사용하여 데이터를 템플릿을 통해 전달할 수 있습니다.
parent.component.ts
import { Component } from '@angular/core';
@Component({
selector: 'parent-component',
template: `
<child-component [childProperty]="parentProperty"></child-component>
`,
styleUrls: ['./parent.component.css']
})
export class ParentComponent{
parentProperty = "I come from parent"
constructor() { }
}
child.component.ts
import { Component, Input } from '@angular/core';
@Component({
selector: 'child-component',
template: `
Hi {{ childProperty }}
`,
styleUrls: ['./child.component.css']
})
export class ChildComponent {
@Input() childProperty: string;
constructor() { }
}
이것은 매우 간단한 방법입니다. 사용하기 쉽습니다. ngOnChanges를 사용하여 자식 구성 요소의 데이터 변경 사항을 잡을 수도 있습니다 .
그러나 객체를 데이터로 사용하고이 객체의 매개 변수를 변경해도 참조는 변경되지 않습니다. 따라서 자식 구성 요소에서 수정 된 개체를 받으려면 변경할 수 없어야합니다.
2. 자녀> 부모
ViewChild를 통한 데이터 공유
ViewChild를 사용하면 한 구성 요소를 다른 구성 요소에 주입하여 부모에게 해당 속성 및 기능에 액세스 할 수 있습니다. 그러나 한 가지주의 child
할 점 은 뷰가 초기화 될 때까지 사용할 수 없다는 것입니다. 즉, 자식에서 데이터를 수신하려면 AfterViewInit 수명주기 후크를 구현해야합니다.
parent.component.ts
import { Component, ViewChild, AfterViewInit } from '@angular/core';
import { ChildComponent } from "../child/child.component";
@Component({
selector: 'parent-component',
template: `
Message: {{ message }}
<child-compnent></child-compnent>
`,
styleUrls: ['./parent.component.css']
})
export class ParentComponent implements AfterViewInit {
@ViewChild(ChildComponent) child;
constructor() { }
message:string;
ngAfterViewInit() {
this.message = this.child.message
}
}
child.component.ts
import { Component} from '@angular/core';
@Component({
selector: 'child-component',
template: `
`,
styleUrls: ['./child.component.css']
})
export class ChildComponent {
message = 'Hello!';
constructor() { }
}
Output () 및 EventEmitter를 통한 데이터 공유
데이터를 공유하는 또 다른 방법은 부모가 나열 할 수있는 자식에서 데이터를 내보내는 것입니다. 이 방법은 버튼 클릭, 양식 항목 및 기타 사용자 이벤트와 같은 데이터 변경 사항을 공유하려는 경우에 이상적입니다.
parent.component.ts
import { Component } from '@angular/core';
@Component({
selector: 'parent-component',
template: `
Message: {{message}}
<child-component (messageEvent)="receiveMessage($event)"></child-component>
`,
styleUrls: ['./parent.component.css']
})
export class ParentComponent {
constructor() { }
message:string;
receiveMessage($event) {
this.message = $event
}
}
child.component.ts
import { Component, Output, EventEmitter } from '@angular/core';
@Component({
selector: 'child-component',
template: `
<button (click)="sendMessage()">Send Message</button>
`,
styleUrls: ['./child.component.css']
})
export class ChildComponent {
message: string = "Hello!"
@Output() messageEvent = new EventEmitter<string>();
constructor() { }
sendMessage() {
this.messageEvent.emit(this.message)
}
}
3. 형제 자매
어린이> 부모> 어린이
아래 형제들과 의사 소통하는 다른 방법을 설명하려고합니다. 그러나 위의 방법을 이해하는 방법 중 하나를 이미 이해할 수 있습니다.
parent.component.ts
import { Component } from '@angular/core';
@Component({
selector: 'parent-component',
template: `
Message: {{message}}
<child-one-component (messageEvent)="receiveMessage($event)"></child1-component>
<child-two-component [childMessage]="message"></child2-component>
`,
styleUrls: ['./parent.component.css']
})
export class ParentComponent {
constructor() { }
message: string;
receiveMessage($event) {
this.message = $event
}
}
child-one.component.ts
import { Component, Output, EventEmitter } from '@angular/core';
@Component({
selector: 'child-one-component',
template: `
<button (click)="sendMessage()">Send Message</button>
`,
styleUrls: ['./child-one.component.css']
})
export class ChildOneComponent {
message: string = "Hello!"
@Output() messageEvent = new EventEmitter<string>();
constructor() { }
sendMessage() {
this.messageEvent.emit(this.message)
}
}
child-two.component.ts
import { Component, Input } from '@angular/core';
@Component({
selector: 'child-two-component',
template: `
{{ message }}
`,
styleUrls: ['./child-two.component.css']
})
export class ChildTwoComponent {
@Input() childMessage: string;
constructor() { }
}
4. 관련없는 구성 요소
아래 설명 된 모든 방법은 구성 요소 간의 관계에 대한 위의 모든 옵션에 사용할 수 있습니다. 그러나 각각의 장점과 단점이 있습니다.
서비스와 데이터 공유
형제, 손자 등 직접 연결이없는 구성 요소간에 데이터를 전달할 때는 공유 서비스를 사용해야합니다. 항상 동기화해야하는 데이터가 있으면이 상황에서 RxJS BehaviorSubject가 매우 유용합니다.
data.service.ts
import { Injectable } from '@angular/core';
import { BehaviorSubject } from 'rxjs';
@Injectable()
export class DataService {
private messageSource = new BehaviorSubject('default message');
currentMessage = this.messageSource.asObservable();
constructor() { }
changeMessage(message: string) {
this.messageSource.next(message)
}
}
first.component.ts
import { Component, OnInit } from '@angular/core';
import { DataService } from "../data.service";
@Component({
selector: 'first-componennt',
template: `
{{message}}
`,
styleUrls: ['./first.component.css']
})
export class FirstComponent implements OnInit {
message:string;
constructor(private data: DataService) {
// The approach in Angular 6 is to declare in constructor
this.data.currentMessage.subscribe(message => this.message = message);
}
ngOnInit() {
this.data.currentMessage.subscribe(message => this.message = message)
}
}
second.component.ts
import { Component, OnInit } from '@angular/core';
import { DataService } from "../data.service";
@Component({
selector: 'second-component',
template: `
{{message}}
<button (click)="newMessage()">New Message</button>
`,
styleUrls: ['./second.component.css']
})
export class SecondComponent implements OnInit {
message:string;
constructor(private data: DataService) { }
ngOnInit() {
this.data.currentMessage.subscribe(message => this.message = message)
}
newMessage() {
this.data.changeMessage("Hello from Second Component")
}
}
경로와 데이터 공유
때로는 구성 요소간에 간단한 데이터를 전달해야 할뿐만 아니라 페이지의 일부 상태를 저장해야합니다. 예를 들어, 온라인 시장에서 일부 필터를 저장 한 다음이 링크를 복사하여 친구에게 보내려고합니다. 그리고 우리와 같은 상태로 페이지를 열 것으로 기대합니다. 가장 빠른 방법은 query parameters 를 사용하는 것 입니다.
쿼리 매개 변수는 더의 라인을 따라 보이는 /people?id=
곳 id
아무 것도 동일 할 수 있고 당신이 원하는대로 당신은 많은 매개 변수로 할 수 있습니다. 쿼리 매개 변수는 앰퍼샌드 문자로 구분됩니다.
쿼리 매개 변수로 작업 할 때 경로 파일에서 매개 변수를 정의 할 필요가 없으며 매개 변수의 이름을 지정할 수 있습니다. 예를 들어 다음 코드를 사용하십시오.
page1.component.ts
import {Component} from "@angular/core";
import {Router, NavigationExtras} from "@angular/router";
@Component({
selector: "page1",
template: `
<button (click)="onTap()">Navigate to page2</button>
`,
})
export class Page1Component {
public constructor(private router: Router) { }
public onTap() {
let navigationExtras: NavigationExtras = {
queryParams: {
"firstname": "Nic",
"lastname": "Raboy"
}
};
this.router.navigate(["page2"], navigationExtras);
}
}
수신 페이지에서 다음과 같은 쿼리 매개 변수가 수신됩니다.
page2.component.ts
import {Component} from "@angular/core";
import {ActivatedRoute} from "@angular/router";
@Component({
selector: "page2",
template: `
<span>{{firstname}}</span>
<span>{{lastname}}</span>
`,
})
export class Page2Component {
firstname: string;
lastname: string;
public constructor(private route: ActivatedRoute) {
this.route.queryParams.subscribe(params => {
this.firstname = params["firstname"];
this.lastname = params["lastname"];
});
}
}
NgRx
더 복잡하지만 더 강력한 마지막 방법은 NgRx 를 사용하는 것 입니다. 이 라이브러리는 데이터 공유를위한 것이 아닙니다. 강력한 상태 관리 라이브러리입니다. 나는 짧은 예제에서 그것을 사용하는 방법을 설명 할 수는 없지만 공식 사이트로 이동하여 관련 문서를 읽을 수 있습니다.
NgRx Store는 여러 가지 문제를 해결합니다. 예를 들어, 관찰 가능 데이터를 처리해야하고 일부 관찰 가능 데이터에 대한 책임이 다른 구성 요소간에 공유되는 경우, 상점 조치 및 감속기는 데이터 수정이 항상 "올바른 방법"으로 수행되도록합니다.
또한 HTTP 요청 캐싱을위한 안정적인 솔루션을 제공합니다. 요청한 요청에 아직 저장된 응답이 없는지 확인할 수 있도록 요청 및 응답을 저장할 수 있습니다.
NgRx에 대해 읽고 앱에 필요한지 여부를 이해할 수 있습니다.
마지막으로, 데이터 공유 방법 중 일부를 선택하기 전에이 데이터가 향후 어떻게 사용되는지 이해해야한다고 말하고 싶습니다. 어쩌면 지금 @Input
은 사용자 이름과 성을 공유하기 위해 데코레이터 만 사용할 수 있습니다 . 그런 다음 사용자에 대한 자세한 정보가 필요한 새 구성 요소 또는 새 모듈 (예 : 관리자 패널)을 추가합니다. 이는 사용자 데이터를위한 서비스를 사용하거나 다른 방법으로 데이터를 공유하는 더 좋은 방법 일 수 있음을 의미합니다. 데이터 공유 구현을 시작하기 전에 더 자세히 고려해야합니다.