Pertama, apa yang Anda butuhkan untuk memahami hubungan antar komponen. Kemudian Anda dapat memilih metode komunikasi yang tepat. Saya akan mencoba menjelaskan semua metode yang saya tahu dan gunakan dalam praktik saya untuk komunikasi antar komponen.
Hubungan macam apa yang bisa terjadi antar komponen?
1. Induk> Anak
Berbagi Data melalui Input
Ini mungkin metode berbagi data yang paling umum. Ini bekerja dengan menggunakan @Input()
dekorator untuk memungkinkan data dikirimkan melalui templat.
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() { }
}
Ini adalah metode yang sangat sederhana. Mudah digunakan. Kami juga dapat menangkap perubahan pada data dalam komponen anak menggunakan ngOnChanges .
Tetapi jangan lupa bahwa jika kita menggunakan objek sebagai data dan mengubah parameter objek ini, referensi untuk itu tidak akan berubah. Oleh karena itu, jika kita ingin menerima objek yang dimodifikasi dalam komponen anak, itu harus tidak berubah.
2. Anak> Orangtua
Berbagi Data melalui ViewChild
ViewChild memungkinkan satu komponen untuk disuntikkan ke yang lain, memberikan orang tua akses ke atribut dan fungsinya. Satu peringatan, bagaimanapun, adalah bahwa child
tidak akan tersedia sampai setelah tampilan diinisialisasi. Ini berarti kita perlu mengimplementasikan kait siklus hidup AfterViewInit untuk menerima data dari anak.
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() { }
}
Berbagi Data melalui Output () dan EventEmitter
Cara lain untuk berbagi data adalah dengan memancarkan data dari anak, yang dapat didaftar oleh orang tua. Pendekatan ini sangat ideal ketika Anda ingin berbagi perubahan data yang terjadi pada hal-hal seperti klik tombol, entri formulir, dan acara pengguna lainnya.
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. Saudara kandung
Anak> Orangtua> Anak
Saya mencoba menjelaskan cara lain untuk berkomunikasi antara saudara kandung di bawah ini. Tetapi Anda sudah bisa memahami salah satu cara memahami metode di atas.
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. Komponen Yang Tidak Terkait
Semua metode yang saya jelaskan di bawah ini dapat digunakan untuk semua opsi di atas untuk hubungan antar komponen. Tetapi masing-masing memiliki kelebihan dan kekurangan.
Berbagi Data dengan Layanan
Saat mengirimkan data antar komponen yang tidak memiliki koneksi langsung, seperti saudara kandung, cucu, dll, Anda harus menggunakan layanan bersama. Ketika Anda memiliki data yang harus selalu disinkronkan, saya menemukan bahwa RxJS BehaviorSubject sangat berguna dalam situasi ini.
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")
}
}
Berbagi Data dengan Rute
Terkadang Anda tidak hanya perlu mengirimkan data sederhana antar komponen tetapi juga menyimpan beberapa kondisi halaman. Misalnya, kami ingin menyimpan beberapa filter di pasar online dan kemudian menyalin tautan ini dan mengirim ke teman. Dan kami berharap untuk membuka halaman dalam kondisi yang sama seperti kami. Cara pertama, dan mungkin yang tercepat, untuk melakukan ini adalah dengan menggunakan parameter kueri .
Parameter kueri terlihat lebih di sepanjang garis di /people?id=
mana id
dapat sama dengan apa pun dan Anda dapat memiliki parameter sebanyak yang Anda inginkan. Parameter kueri akan dipisahkan oleh karakter ampersand.
Saat bekerja dengan parameter kueri, Anda tidak perlu mendefinisikannya dalam file rute Anda, dan mereka bisa dinamai parameter. Misalnya, ambil kode berikut:
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);
}
}
Di halaman penerimaan, Anda akan menerima parameter kueri ini seperti berikut:
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
Cara terakhir, yang lebih rumit tetapi lebih kuat, adalah menggunakan NgRx . Perpustakaan ini bukan untuk berbagi data; itu adalah perpustakaan manajemen negara yang kuat. Dalam contoh singkat saya tidak dapat menjelaskan cara menggunakannya, tetapi Anda dapat mengunjungi situs resmi dan membaca dokumentasi tentangnya.
Bagi saya, NgRx Store memecahkan banyak masalah. Misalnya, ketika Anda harus berurusan dengan yang dapat diobservasi dan ketika tanggung jawab untuk beberapa data yang dapat diamati dibagi antara komponen yang berbeda, tindakan toko dan peredam memastikan bahwa modifikasi data akan selalu dilakukan "dengan cara yang benar".
Ini juga menyediakan solusi yang andal untuk caching permintaan HTTP. Anda akan dapat menyimpan permintaan dan responsnya sehingga Anda dapat memverifikasi bahwa permintaan yang Anda buat belum memiliki respons tersimpan.
Anda dapat membaca tentang NgRx dan memahami apakah Anda membutuhkannya di aplikasi Anda atau tidak:
Akhirnya, saya ingin mengatakan bahwa sebelum memilih beberapa metode untuk berbagi data, Anda perlu memahami bagaimana data ini akan digunakan di masa depan. Maksud saya mungkin barusan Anda hanya dapat menggunakan @Input
dekorator untuk berbagi nama pengguna dan nama keluarga. Kemudian Anda akan menambahkan komponen baru atau modul baru (misalnya, panel admin) yang membutuhkan informasi lebih lanjut tentang pengguna. Ini berarti bahwa mungkin cara yang lebih baik untuk menggunakan layanan untuk data pengguna atau cara lain untuk berbagi data. Anda harus lebih memikirkannya sebelum mulai menerapkan berbagi data.