1.父组件通过属性绑定的方式将数组从上到下的流入到子组件中,子组件需要通过@Input装饰器来获取。
例如:
父组件为
@Component({
template: `
-
`
})
export class ListComponent implement OnInit{
this.contacts = data;
}
子组件为:
@Component({
template:`
`
})
export class ListItemComponent implements OnInit{
@Input() contact: any = {};
}
2.子组件通过事件传递的方式向父组件传递数据,子组件需要实例化EventEmitter类,并使用装饰器@Output修饰这个输出属性。父组件通过事件绑定的方式来订阅来自子组件触发的事件。
父组件:
@Component({
template: `
`
})
export class CollectionComponent implements OnInit{
detail: any = {};
collectTheContact(){
this.detail.collection == 0 ? this.detail.collection = 1 : this.detail.collection = 0;
}
}
父组件通过绑定自定义事件onCollect订阅来自子组件触发的事件。
子组件
@Component({
template: `收藏`
})
export class ContactCollectComponent{
@Input() contact: any = {};
@Output() onCollect = new EventEmitter();
collectTheContact(){
this.onCollect.emit();
}
}
通过@Output将数据流向父组件。
3.父组件通过局部变量获取子组件的引用、父组件使用@ViewChild获取子组件的引用
(1)在父组件的模板中为子组件创建一个局部变量,就可以在父组件的模板中访问子组件的所有属性和方法。这个局部变量有局限性,因为模板变量只能在模板中使用,父组件的类不能使用这个局部变量访问子组件的属性和方法。
例如
父组件:
@Component({
template:`
`
})
export class CollectionComponent{}
在父组件中为子组件创建了一个局部变量#collect,父组件就可以使用#collect调用子组件的方法collectTheContact()
子组件
@Component({
template:收藏
})
export class ContactCollectComponent{
detail: any = {};
collectTheContact(){
this.detail.collection == 0 ? this.detail.collection = 1 : this.detail.collection = 0;
}
}
(2)使用@ViewChid属性装饰器获取子组件的引用,该方法获取的引用可以在父组件类中使用。
@ViewChild()提供了一个参数来选择将要引用的组件元素。这个参数可以是一个类的实例,也可以是字符串。
I.参数为类实例,表示父组件将绑定一个指令或者子组件实例
II.参数为字符串类型,相当于在父组件中绑定一个模板局部变量,获取到子组件的一个实例对象的引用。
参数为字符串
@ViewChild("dateRange")
private dateRange: OpsDateRangeComponent;
参数为类实例
@Component({
template:`
`
})
export class CollectionComponent{
@ViewChild(ContactCollectComponent) contactCollect: ContactCollectComponent;
ngAfterViewInit(){}
collectTheContact(){
this.contactCollect.collectTheContact();
}
}
组件内容嵌入
例如:
@Component({
selector: 'example-content'
template: `
ng-content实例
`
})
class NgContentExampleComponent{}
中有一个select="header",用于匹配内容。并填充到ng-content中。
使用
@Component({
selector:'app'
template:`
Header content
`
})
export class NgContentAppComponent{}
最后渲染成的是
ng-content
Header content
从图中可以看出Header content 被填充到了ng-content,select属性是一个选择器,类似于css的选择器,可以有标签选择器、类选择器、属性选择器。
4.通过setter监听输入属性值的变化
使用一个输入属性的setter,来拦截父组件中值的变化,并采取行动。
import { Component, Input } from '@angular/core';
@Component({
selector: 'app-name-child',
template: '"{{name}}"
'
})
export class NameChildComponent {
private _name = '';
@Input()
set name(name: string) {
this._name = (name && name.trim()) || '';
}
get name(): string { return this._name; }
}
在组件Namechildcomponent的输入属性name上设置了setter,会将父组件传回来的name去掉空格,或者将空值替换成默认的字符串。
5.通过ngOnChanges()来监听输入属性值的变化
使用OnChanges声明周期钩子接口的ngOnChanges()方法来监测输入属性值的变化并做出回应。(相比于setter方式,该方式可以舰艇多个输入属性)
import { Component, Input, OnChanges, SimpleChange } from '@angular/core';
@Component({
selector: 'app-version-child',
template: `
Version {{major}}.{{minor}}
Change log:
- {{change}}
`
})
export class VersionChildComponent implements OnChanges {
@Input() major: number;
@Input() minor: number;
changeLog: string[] = [];
ngOnChanges(changes: {[propKey: string]: SimpleChange}) {
let log: string[] = [];
for (let propName in changes) {
let changedProp = changes[propName];
let to = JSON.stringify(changedProp.currentValue);
if (changedProp.isFirstChange()) {
log.push(`Initial value of ${propName} set to ${to}`);
} else {
let from = JSON.stringify(changedProp.previousValue);
log.push(`${propName} changed from ${from} to ${to}`);
}
}
this.changeLog.push(log.join(', '));
}
}
这个VersionChildComponent 组件会监测major和minor属性的变化,并把这些变化写成日志报告出来。
VersionChildComponent 提供minor和major值,把修改它们值的方法绑定到按钮上。
import { Component } from '@angular/core';
@Component({
selector: 'app-version-parent',
template: `
Source code version
`
})
export class VersionParentComponent {
major = 1;
minor = 23;
newMinor() {
this.minor++;
}
newMajor() {
this.major++;
this.minor = 0;
}
}
父组件和子组件通过服务来进行通讯
父组件和子组件共享同一个服务,利用该服务在组件家族中实现双向通讯。
例如:
服务:
import { Injectable } from '@angular/core';
import { Subject } from 'rxjs';
@Injectable()
export class MissionService {
// Observable string sources
private missionAnnouncedSource = new Subject();
private missionConfirmedSource = new Subject();
// Observable string streams
missionAnnounced$ = this.missionAnnouncedSource.asObservable();
missionConfirmed$ = this.missionConfirmedSource.asObservable();
// Service message commands
announceMission(mission: string) {
this.missionAnnouncedSource.next(mission);
}
confirmMission(astronaut: string) {
this.missionConfirmedSource.next(astronaut);
}
}
MissionControlComponent 提供服务的实例,并将其共享给它的子组件(通过 providers 元数据数组),子组件可以通过构造函数将该实例注入到自身.
import { Component } from '@angular/core';
import { MissionService } from './mission.service';
@Component({
selector: 'app-mission-control',
template: `
Mission Control
History
- {{event}}
`,
providers: [MissionService]
})
export class MissionControlComponent {
astronauts = ['Lovell', 'Swigert', 'Haise'];
history: string[] = [];
missions = ['Fly to the moon!',
'Fly to mars!',
'Fly to Vegas!'];
nextMission = 0;
constructor(private missionService: MissionService) {
missionService.missionConfirmed$.subscribe(
astronaut => {
this.history.push(`${astronaut} confirmed the mission`);
});
}
announce() {
let mission = this.missions[this.nextMission++];
this.missionService.announceMission(mission);
this.history.push(`Mission "${mission}" announced`);
if (this.nextMission >= this.missions.length) { this.nextMission = 0; }
}
}
AstronautComponent 也通过自己的构造函数注入该服务。由于每个 AstronautComponent 都是 MissionControlComponent 的子组件,所以它们获取到的也是父组件的这个服务实例。
import { Component, Input, OnDestroy } from '@angular/core';
import { MissionService } from './mission.service';
import { Subscription } from 'rxjs';
@Component({
selector: 'app-astronaut',
template: `
{{astronaut}}: {{mission}}
`
})
export class AstronautComponent implements OnDestroy {
@Input() astronaut: string;
mission = '';
confirmed = false;
announced = false;
subscription: Subscription;
constructor(private missionService: MissionService) {
this.subscription = missionService.missionAnnounced$.subscribe(
mission => {
this.mission = mission;
this.announced = true;
this.confirmed = false;
});
}
confirm() {
this.confirmed = true;
this.missionService.confirmMission(this.astronaut);
}
ngOnDestroy() {
// prevent memory leak when component destroyed
this.subscription.unsubscribe();
}
}