angular应用就是一个组件树
要创建松耦合的组件
组件通信的例子
新生成一个项目ng new demo2
或者通过webstorm,File,New,Project..,Angular CLI,然后把项目名改成demo2
因为要用双向绑定,在app.module.ts中添加
import{FormsModule} from '@angular/forms'
imports: [
BrowserModule,
FormsModule
],
从父组件传递数据到子组件
组件间通信是单向的,从父组件传递到子组件。
新建一个组件ng g component order
修改order.component.ts
import { Component, OnInit ,Input} from '@angular/core';
@Component({
selector: 'app-order',
templateUrl: './order.component.html',
styleUrls: ['./order.component.css']
})
export class OrderComponent implements OnInit {
@Input()
stockCode:string;
@Input()
amount:number;
constructor() { }
ngOnInit() {
}
}
修改order.component.html
<p>
我是子组件
</p>
<p>
买{{amount}}手{{stockCode}}股票
</p>
修改其父组件app,修改app.component.ts
import { Component } from '@angular/core';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
stock="";
title = 'app';
}
修改app.component.html
<div>
我是父组件
</div>
<div>
<input type="text" placeholder="请输入股票代码" [(ngModel)]="stock">
<app-order [stockCode]="stock" [amount]="100" ></app-order>
</div>
组件间通信是单向的,只能从父组件到子组件
启动项目。
子组件的数据传输到父组件
新建一个组件ng g component priceQuote
修改price-quote.component.ts
import { Component, OnInit } from '@angular/core';
@Component({
selector: 'app-price-quote',
templateUrl: './price-quote.component.html',
styleUrls: ['./price-quote.component.css']
})
export class PriceQuoteComponent implements OnInit {
stockCode:string="IBM";
price:number;
constructor() {
setInterval(()=>{
let priceQuote:PriceQuote=new PriceQuote(this.stockCode,100*Math.random())
this.price=priceQuote.lastPrice;
},1000)
}
ngOnInit() {
}
}
export class PriceQuote{
constructor(public stockCode:string,
public lastPrice:number){
}
}
修改price-quote.component.html
<div>
这里是报价组件
</div>
<div>
股票代码是{{stockCode}},股票价格是{{price|number:'2.2-2'}}
</div>
修改app.component.html
<!--<div>-->
<!--我是父组件-->
<!--</div>-->
<!--<div>-->
<!--<input type="text" placeholder="请输入股票代码" [(ngModel)]="stock">-->
<!--<app-order [stockCode]="stock" [amount]="100" ></app-order>-->
<!--</div>-->
<app-price-quote></app-price-quote>
启动项目
现在我要把子组件中的数据传到父组件
修改price-quote.component.ts
import {Component, OnInit, EventEmitter, Output} from '@angular/core';
@Component({
selector: 'app-price-quote',
templateUrl: './price-quote.component.html',
styleUrls: ['./price-quote.component.css']
})
export class PriceQuoteComponent implements OnInit {
stockCode: string = "IBM";
price: number;
//EventEmitter既可以当被观察者也可以当观察者
/**
* 泛型规定的是向外发射的是什么类型的
* @type {EventEmitter<any>}
*/
@Output()
lastPrice: EventEmitter<PriceQuote> = new EventEmitter();
constructor() {
setInterval(() => {
let priceQuote: PriceQuote = new PriceQuote(this.stockCode, 100 * Math.random())
this.price = priceQuote.lastPrice;
this.lastPrice.emit(priceQuote);//用emit向外发射
}, 1000)
}
ngOnInit() {
}
}
export class PriceQuote {
constructor(public stockCode: string,
public lastPrice: number) {
}
}
修改app.component.ts
import { Component } from '@angular/core';
import {PriceQuote} from "./price-quote/price-quote.component";
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
stock="";
priceQuote:PriceQuote=new PriceQuote("",0);
priceQuoteHandler(event:PriceQuote){//接收子组件传递过来的数据
this.priceQuote=event;
}
}
修改app.component.html
<!--<div>-->
<!--我是父组件-->
<!--</div>-->
<!--<div>-->
<!--<input type="text" placeholder="请输入股票代码" [(ngModel)]="stock">-->
<!--<app-order [stockCode]="stock" [amount]="100" ></app-order>-->
<!--</div>-->
<app-price-quote (lastPrice)="priceQuoteHandler($event)"></app-price-quote>
<div>
这是在报价组件外部,
<div>
</div>
股票代码是{{priceQuote.stockCode}},
股票价格是{{priceQuote.lastPrice|number:'2.2-2'}}
</div>
启动项目
其中price-quote.component.ts
/**
EventEmitter既可以当观察者也可以当被观察者
其中泛型规定的是向外发射的是什么类型的
*/
@Output()
lastPrice: EventEmitter<PriceQuote> = new EventEmitter();
this.lastPrice.emit(priceQuote);//用emit方法向外发射
其中在app.component.html中
<app-price-quote (lastPrice)="priceQuoteHandler($event)"></app-price-quote>
默认情况下里边的lastPrice要和price-quote.component.ts中的lastPrice一样。
如果想不一样的话可以
@Output('priceChange')
lastPrice: EventEmitter<PriceQuote> = new EventEmitter();
<app-price-quote (priceChange)="priceQuoteHandler($event)"></app-price-quote>
现在这种情况只能由其父组件来绑定事件并处理。如果两个组件不存在父子关系,怎么以一种松耦合的方式传递数据呢?
中间人模式
中间人组件负责从一个组件接受数据并传递给另一个组件。
修改price-quote.component.html
<div>
这里是报价组件
</div>
<div>
股票代码是{{stockCode}},股票价格是{{price|number:'2.2-2'}}
</div>
<div>
<input type="button" value="立即购买" (click)="buyStock($event)">
</div>
在price-quote.component.ts中添加
@Output()
buy:EventEmitter<PriceQuote>=new EventEmitter();
buyStock(event){
this.buy.emit(new PriceQuote(this.stockCode,this.price));
}
修改app.component.html
<app-price-quote (buy)="buyHandler($event)"></app-price-quote>
<app-order [priceQuote]="priceQuote"></app-order>
修改app.component.ts
export class AppComponent {
//stock="";
priceQuote:PriceQuote=new PriceQuote("",0);
buyHandler(event:PriceQuote){
this.priceQuote=event;
}
}
修改order.component.ts
export class OrderComponent implements OnInit {
@Input()
priceQuote:PriceQuote;
constructor() { }
ngOnInit() {
}
}
修改order.component.html
<p>
我是下单组件
</p>
<p>
买100手{{priceQuote.stockCode}}股票,买入价格是{{priceQuote.lastPrice | number:'2.2-2'}}
</p>
priceQuote组件通过app组件这个中间人把数据传给order组件。
app是priceQuote和order这两个兄弟组件的父组件。
如果没有父组件这种关系,可以定义一个服务来做实现中间人的功能。