組件化是Angular的核心概念培愁,所以組件通信的使用就比較多而且很重要。
官方傳送門??:
https://angular.io/guide/component-interaction , https://angular.cn/guide/component-interaction
父子組件通信
關(guān)鍵詞 Input Output EventEmitter ViewChild
1凉翻、父組件 向 子組件 傳遞數(shù)據(jù)
【Input】
綁定屬性的方式
父組件:
<!-- parentComponent -->
<app-child [name]="'childName'"></app-child>
子組件:
// 子組件需要使用Input接收
<span>{{name}}</span>
@Input() public name:string = '';
2嗜傅、子組件 向 父組件 傳遞數(shù)據(jù)
【Output EventEmitter】
子組件:
@Output()
public readonly childEmit: EventEmitter<T> = new EventEmitter<T>();
this.childEmit.emit(data);
父組件:
<app-child (childEmit)="getData($event)"></app-child>
public getData(data:T): void { }
3、ViewChild 方法
因?yàn)槲矣X得這個方法既可以讓父組件獲取子組件的數(shù)據(jù)泪勒,又可以讓父組件給子組件設(shè)置變量值等跌前,所以我這里單獨(dú)分了出來棕兼。
父組件:
<app-child **#child**></app-child>
<button (click)="**child**.print('---')">點(diǎn)擊</button>
@ViewChild('child', { static: true })
public child!: ElementRef<HTMLElement>;
public print():void{
if(this.child){
// 這里得到child,可以使用child中的所有的public屬性方法
this.child.print('hello2');
}
}
【示例】
// 父組件
import { Component } from '@angular/core';
@Component({
selector: 'app-parent',
template: `
<app-child #child [name]="name" (childEmit)="childClick($event)"></app-child>
<button (click)="child.print('hello1')">調(diào)用子組件的方法1</button>
<button (click)="print()">調(diào)用子組件的方法2</button>
`
})
export class ParentComponent {
public name:string = '大兒子';
@ViewChild('child', { static: true })
public child!: ElementRef<HTMLElement>;
public childClick(bool:Boolean):void{
// TODO
}
public print():void{
if(this.child){
this.child.print('hello2');
}
}
}
/*****************************************************/
// 子組件
import { Component, Input, Output, EventEmitter } from '@angular/core';
@Component({
selector: 'app-child',
template: `
<h3 (click)="myClick()">{{name}}</h3>
`
})
export class HeroChildComponent {
@Input()
public name: string;
@Output()
public readonly childEmit: EventEmitter<boolean> = new EventEmitter<boolean>();
public myClick():void{
this.childEmit.emit(true);
}
public print(content:string):void{
console.log(content);
}
}
非父子組件通信
1抵乓、Service
單例模式伴挚,其實(shí)就是一個變量,需要雙向觸發(fā)(發(fā)送信息 / 接收信息)灾炭,及設(shè)置和獲取數(shù)據(jù)都需要組件自己去處理茎芋。
service.ts
import { Component, Injectable, EventEmitter } from '@angular/core';
@Injectable()
export class myService {
public info: string = '';
}
組件 1 向 service 傳遞信息
import { Service1 } from '../../service/service1.service';
...
public constructor(
public service: Service1,
) { }
public changeInfo():void {
this.service.info = this.service.info + '1234';
}
...
組件 2 從 service 獲取信息
import { Service2 } from '../../service/service2.service';
...
public constructor(
public service: Service2,
) { }
public showInfo() {
console.log(this.service.info);
}
...
2、Subject(發(fā)布訂閱)
真正的發(fā)布訂閱模式蜈出,當(dāng)數(shù)據(jù)改變時田弥,訂閱者也能得到響應(yīng),這里只舉了BehaviorSubject的例子
// Service
import { BehaviorSubject } from 'rxjs';
...
public messageSource = new BehaviorSubject<string>('Start');
public changeMessage(message: string): void {
this.messageSource.next(message);
}
public getMessageSource(): Observable<string> {
return this.messageSource.asObservable();
}
/////////////////////////
// 發(fā)布
...
this.messageService.changeMessage('message change');
/////////////////////////
public
// 訂閱 (記得根據(jù)需要選擇是否取消訂閱 unsubscribe)
this.messageService.getMessageSource().subscribe(m => {
console.log(m);
})
四種主題Subject對比??
rxjs subject | 是否存儲數(shù)據(jù) | 是否需要初始值 | 何時向訂閱者發(fā)布數(shù)據(jù) |
---|---|---|---|
Subject | 否 | 否 | 及時發(fā)布。有新數(shù)據(jù)就發(fā)布 |
BehaviorSubject | 是铡原。存儲最后一條數(shù)據(jù)或者初始值 | 是 | 及時發(fā)布偷厦。有新數(shù)據(jù)就發(fā)布 |
ReplaySubject | 是。存儲所有數(shù)據(jù) | 否 | 及時發(fā)布燕刻。有新數(shù)據(jù)就發(fā)布 |
AsyncSubject | 是沪哺。存儲最后一條數(shù)據(jù) | 是 | 延時發(fā)布。只有當(dāng)數(shù)據(jù)源complete的時候才會發(fā)布 |
其他通信方式??
路由傳值酌儒、瀏覽器本地存儲(LocalStorage,SessionStorage)枯途、cookie忌怎。