- 0133技术站
- 联系QQ:18840023
- QQ交流群
- 微信公众号
组件通信
本文介绍的内容是组件通信的常用方式:@Input、@Output、@ViewChild、模板变量、MessageService、Broadcaster (Angular 1.x $rootScope 中 $on、$broadcast ) 和 Pub - Sub 模式、RxJS Subject 存在的问题。
输入属性 (父组件 -> 子组件)
counter.component.ts
import { Component, Input } from '@angular/core'; @Component({ selector: 'exe-counter', template: ` <p>当前值: {{ count }}</p> <button (click)="increment()"> + </button> <button (click)="decrement()"> - </button> ` }) export class CounterComponent { @Input() count: number = 0; increment() { this.count++; } decrement() { this.count--; } }
app.component.ts
import { Component } from '@angular/core'; @Component({ selector: 'exe-app', template: ` <exe-counter [count]="initialCount"></exe-counter> ` }) export class AppComponent { initialCount: number = 5; }
输出属性 (子组件 -> 父组件)
counter.component.ts
import { Component, Input, Output, EventEmitter } from '@angular/core'; @Component({ selector: 'exe-counter', template: ` <p>当前值: {{ count }}</p> <button (click)="increment()"> + </button> <button (click)="decrement()"> - </button> ` }) export class CounterComponent { @Input() count: number = 0; @Output() change: EventEmitter<number> = new EventEmitter<number>(); increment() { this.count++; this.change.emit(this.count); } decrement() { this.count--; this.change.emit(this.count); } }
app.component.ts
import { Component } from '@angular/core'; @Component({ selector: 'exe-app', template: ` <p>{{changeMsg}}</p> <exe-counter [count]="initialCount" (change)="countChange($event)"></exe-counter> ` }) export class AppComponent { initialCount: number = 5; changeMsg: string; countChange(event: number) { this.changeMsg = `子组件change事件已触发,当前值是: ${event}`; } }
模板变量
child.component.ts
import {Component} from '@angular/core'; @Component({ selector: 'child-component', template: `I'm {{ name }}` }) export class ChildComponent { public name: string; }
parent.component.ts
import {Component, OnInit} from '@angular/core'; import {ChildComponent} from './child-component.ts'; @Component({ selector: 'parent-component', template: ` <child-component #child></child-component> <button (click)="child.name = childName">设置子组件名称</button> ` }) export class ParentComponent implements OnInit { private childName: string; constructor() { } ngOnInit() { this.childName = 'child-component'; } }
@ViewChild 装饰器
child.component.ts
import { Component, OnInit } from '@angular/core'; @Component({ selector: 'exe-child', template: ` <p>Child Component</p> ` }) export class ChildComponent { name: string = ''; }
app.component.ts
import { Component, ViewChild, AfterViewInit } from '@angular/core'; import { ChildComponent } from './child.component'; @Component({ selector: 'my-app', template: ` <h4>Welcome to Angular World</h4> <exe-child></exe-child> `, }) export class AppComponent { @ViewChild(ChildComponent) childCmp: ChildComponent; ngAfterViewInit() { this.childCmp.name = 'child-component'; } }
使用 MessageService - 基于 RxJS Subject
message.service.ts
import { Injectable } from '@angular/core'; import {Observable} from 'rxjs/Observable'; import { Subject } from 'rxjs/Subject'; @Injectable() export class MessageService { private subject = new Subject<any>(); sendMessage(message: string) { this.subject.next({ text: message }); } clearMessage() { this.subject.next(); } getMessage(): Observable<any> { return this.subject.asObservable(); } }
home.component.ts
import { Component } from '@angular/core'; import { MessageService } from './message.service'; @Component({ selector: 'exe-home', template: ` <div> <h1>Home</h1> <button (click)="sendMessage()">Send Message</button> <button (click)="clearMessage()">Clear Message</button> </div>` }) export class HomeComponent { constructor(private messageService: MessageService) {} sendMessage(): void { this.messageService.sendMessage('Message from Home Component to App Component!'); } clearMessage(): void { this.messageService.clearMessage(); } }
app.component.ts
import { Component, OnDestroy } from '@angular/core'; import { Subscription } from 'rxjs/Subscription'; import { MessageService } from './message.service'; @Component({ selector: 'my-app', template: ` <div> <div *ngIf="message">{{message.text}}</div> <exe-home></exe-home> </div> ` }) export class AppComponent implements OnDestroy { message: any; subscription: Subscription; constructor(private messageService: MessageService) { this.subscription = this.messageService .getMessage().subscribe( message => { this.message = message; }); } ngOnDestroy() { this.subscription.unsubscribe(); } }
使用 Broadcaster - 基于 RxJS Subject
实现 Angular 1.x 中的 $rootScope 对象中 $on 和 $broadcast 的功能。
broadcaster.ts
import { Injectable } from '@angular/core'; import {Subject} from 'rxjs/Subject'; import {Observable} from 'rxjs/Observable'; import 'rxjs/add/operator/filter'; import 'rxjs/add/operator/map'; interface BroadcastEvent { key: any; data?: any; } @Injectable() export class Broadcaster { private _eventBus: Subject<BroadcastEvent>; constructor() { this._eventBus = new Subject<BroadcastEvent>(); } broadcast(key: any, data?: any) { this._eventBus.next({key, data}); } on<T>(key: any): Observable<T> { return this._eventBus.asObservable() .filter(event => event.key === key) .map(event => <T>event.data); } }
child.component.ts
import { Component } from '@angular/core'; @Component({ selector: 'child' }) export class ChildComponent { constructor(private broadcaster: Broadcaster) {} registerStringBroadcast() { this.broadcaster.on<string>('MyEvent') .subscribe(message => { ... }); } emitStringBroadcast() { this.broadcaster.broadcast('MyEvent', 'some message'); } }
推荐手册