组件化是Angular的核心概念,所以组件通信的使用就比较多而且很重要。
官方传送门:
https://angular.io/guide/component-interaction
https://angular.cn/guide/component-interaction
相关教程推荐:《angular教程》
父子组件通信
关键词 Input Output EventEmitter ViewChild
1、父组件 向 子组件 传递数据
【Input】
绑定属性的方式
父组件:
<!-- parentComponent --> <app-child [name]="'childName'"></app-child>
子组件:
// 子组件需要使用Input接收
<span>{{name}}</span>
@Input() public name:string = '';
2、子组件 向 父组件 传递数据
【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 方法
因为我觉得这个方法既可以让父组件获取子组件的数据,又可以让父组件给子组件设置变量值等,所以我这里单独分了出来。
父组件:
<app-child **#child**></app-child> <button (click)="**child**.print('---')">点击</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')">调用子组件的方法1</button> <button (click)="print()">调用子组件的方法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
单例模式,其实就是一个变量,需要双向触发(发送信息 / 接收信息),及设置和获取数据都需要组件自己去处理。
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(发布订阅)
真正的发布订阅模式,当数据改变时,订阅者也能得到响应,这里只举了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(); } ///////////////////////// // 发布 ... this.messageService.changeMessage('message change'); ///////////////////////// public // 订阅 (记得根据需要选择是否取消订阅 unsubscribe) this.messageService.getMessageSource().subscribe(m => { console.log(m); })
四种主题Subject对比
Subject否否及时发布。有新数据就发布BehaviorSubject是。存储最后一条数据或者初始值是及时发布。有新数据就发布ReplaySubject是。存储所有数据否及时发布。有新数据就发布AsyncSubject是。存储最后一条数据是延时发布。只有当数据源complete的时候才会发布其他通信方式
路由传值、浏览器本地存储(LocalStorage,SessionStorage)、cookie。
更多编程相关知识,可访问:编程入门!!