新版的 Angular 中,子组件和父组件间的通信,采用来事件的机制。这样的设计有助于组件的复用和代码的解耦;
我们不需要过多的关心组件的具体实现,我们只需要知道一个组件它接收哪些数据,并产生哪些输出事件即可。
直接上代码直观了解一下:
@Component({ moduleId: module.id, selector: 'child-component', template: `I'm {{ name }}` }) export class ChildComponent { @Input() name: string; @Output() say: EventEmitter<boolean> = new EventEmitter<boolean>(); ngOnChanges(changes: SimpleChange) { this.name = changes['childName'].currentValue; } speak() { this.say.emit(true); } }
子组件变更完成后,我们来变更父组件的代码实现。
import { Component, OnInit } from '@angular/core'; import { ChildComponent } from './child-component'; @Component({ moduleId: module.id, selector: 'parent-component', template: `<child-component [name]="childName" (say)="isChildSpeak($event)"></child-component>`, // This is unnecessary when installing ChildComponent within Root NgModule directives: [ChildComponent] }) export class ParentComponent implements OnInit { private childName: string; constructor() { } ngOnInit() { this.childName = 'StevenShen'; } isChildSpeak(isIt: boolean) { console.log('The child speak status is %s', isIt ? 'ture' : 'false'); } }
这样一来就实现了父子组件间的通信了。
但是这样的实现存在一定的局限性:父组件不能使用数据绑定来读取子组件的属性或调用子组件的方法.
通过 @ViewChild 获取组件的控制器/模版进行组件间的通信
除开使用 @Input 和 @Output 修饰器搭配Angular的生命周期钩子函数进行组件间通信。 我们还可以采用@ViewChild来进行不同组件间的通信,而不仅仅局限于父子组件间的通信。同时,采用@ViewChild的方式, 我们可以获得更为精细的组件控制权限,比如在父组件中读取子组件的属性值或调用子组件的方法。我们依然采用上面的代码来进行改造。
对于ChildComponent组件的变更:
import { Component } from '@angular/core'; @Component({ moduleId: module.id, selector: 'child-component', template: `I'm {{ name }}` }) export class ChildComponent { public name: string; speak() { console.log('say something whitout EventEmitter'); } }
对于ParentComponent组件的变更:
import { Component, OnInit, AfterViewInit, ViewChild, ElementRef } from '@angular/core'; import { ChildComponent } from './child-component.ts'; @Component({ moduleId: module.id, selector: 'parent-component', // attention #childCmp tag template: ` <child-component #childCmp></child-component> <button (click)="child.name = childName"></button> `, // This is unnecessary when installing ChildComponent within Root NgModule directives: [ ChildComponent ] }) export class ParentComponent implements OnInit, AfterViewInit { @ViewChild('childCmp') childCmp: ElementRef; constructor() { } ngOnInit() { this.childCmp.name = 'StevenShen'; } ngAfterViewInit() { this.childCmp.speak(); } }
通过上面的代码改造,我们同样可以实现不同组件间的通信,而且这样的组件通信已经不仅仅局限于父子组件间的通信了。