组件可以使用一个EventEmitter对象来发射自定义的事件,这些事件可以被其他组件处理,EventEmitter是RXJS的subscribe类的一个子类,在响应式编程中,既可以做观察者,又可以做被观察者。EventEmitter对象既可以emit方法发射自定义事件,也可以通过subscribe来订阅EventEmitter发射的事件流。(EventEmitter后的类型同emit类型一样,和父组件声明的一样)
如何使用EventEmitter从组件内部向外部发射事件?
案例:写一个组件,组件链接股票交易所,显示变动价格,为了组件重用,将最新价格发送到组件之外。其他组件可以执行相应逻辑。(写一个事件,用emit发一个事件,然后父组件接收一个事件。)
步骤1:ng g component priceQuote;
priceQuote.ts
export class PriceQuoteComponent implements OnInit {
/*单独声明两个属性,用来和模板绑定。*/
stockCode = 'IBM';
price: number;
constructor() { }
ngOnInit() {
}
}
// 首先定义报价对象,封装股票价格信息。
// 将特定的数据结构,用类或接口来明确的定义是一个良好的习惯。
export class PriceQuote {
constructor(public stockCode: string, public lastPrice: number) {
}
priceQuote.html
<p>
这里是报价组件
</p>
<div>
股票代码是{{stockCode}},股票价格是{{price | number:'2.2-2'}}
</div>
app.html
<app-price-quote></app-price-quote>
效果:image.png
步骤2:模拟股票价格完成,priceQuote.ts
constructor() {
setInterval(() => {
// 生成一个变量,类型是priceQuote
const priceQuote: PriceQuote = new PriceQuote(this.stockCode, 100 * Math.random());
this.price = priceQuote.lastPrice; /*价格等于最新生成的价格*/
}, 1000);
}
效果:image.png
步骤3:priceQuote.ts,把信息发射出去,谁感兴趣谁订阅(步骤4加两句代码)
// 信息输出出去,谁感兴趣来订阅它,EventEmitter需要一个泛型。lastPrice,可以发射事件,也可以订阅事件,发射事件,写上output
@Output()
lastPrice: EventEmitter<PriceQuote> = new EventEmitter();// 泛型就是你要往外发的数据是什么类型的,
constructor() {
setInterval(() => {
this.lastPrice.emit(priceQuote); /*emit一个值出去,当前最新的报价*/
}, 1000);
}
步骤4:在父组件中接收然后显示。app.ts
priceQuote: PriceQuote = new PriceQuote('', 0);
// 发射的事件是这个类型的,声明这个类型属性,接收发射的报价信息
app.html
<div>
这是组件外部,股票代码是{{priceQuote.stockCode}}
股票价格是{{priceQuote.lastPrice | number:'2.2-2'}}
</div>
效果:image.png
捕捉 子组件发射的这个事件lastPrice
app.html
<!--自定义事件的名字和输出的名字一样@Output('priceChange')需要捕获的那个事件的名字,下面可以改成(priceChange)-->
<app-price-quote (lastPrice)="priceQuoteHandler($event)"></app-price-quote>
app.ts
priceQuoteHandler(event: PriceQuote) {
// 方法里接收一个event:PriceQuote,事件的类型就是子组件发射emit的类型,父组件通过这个类型就能拿到它。子组件发射的报价就被父组件拿到了。
this.priceQuote = event;
// this.priceQuote =event;把本地的变量等于 捕获的事件
}
效果:image.png
我们学习了如何使用输出属性来向组件外发射事件,并通过事件携带数据,这个事件只能有父组件模板通过事件绑定的方式处理,如果不存在父子关系,使用中间人模式