Angular的核心思想就是组件话,我们可以将组件做成一个独立的应用模块来使用。实际开发过程中,我们会发现在应用中有很多功能可以抽象化,可以复用。
想要把一个通用的功能封装成组件,实现功能复用,那么我们的组件就需要有输入、输出,这就是组件交互。
输入型属性
在Angular中,我们使用@Input装饰器来为组件创建输入型属性。
我们定义一个DemoComponent,包含两个输入型属性:
import { Component, Input } from '@angular/core';@Component({selector: 'app-demo',template: `<p>name值为: {{name}}</p><p>masterName值为:{{masterName}}</p>`})export class DemoComponent {@Input() name: string;@Input('master') masterName: string;}
第一个输入属性是name。
第二个输入属性是masterName,通过@Input装饰器,我们为该属性指定了一个别名master。
这样,组件的输入型属性我们就定义完成了。
我们接下来就可以在html中使用demo组件:
<app-demo name="Angular" master="真棒!"></app-demo>
输入属性setter截听
使用一个输入属性的setter,可以截听从父组件传过来的属性内容,并做相应处理。
Demo2Component的输入属name上使用setter,使用trim方法,trim掉输入的空格,并把空值替换成默认字符串。
import { Component, Input } from '@angular/core';@Component({selector: 'app-demo2',template: '<h3>"{{name}}"</h3>'})export class Demo2Component {private _name = '';@Input()set name(name: string) {this._name = (name && name.trim()) || '没有输入';}get name(): string { return this._name; }}
在父组件中使用方式还是和上面一样:
<app-demo2 name=" 我前面有空格"></app-demo2><app-demo2 name="我后面后空格"></app-demo2><app-demo2 name=" "></app-demo2>
实际渲染效果如下:
我前面有空格我后面后空格没有输入
ngOnChanges()
使用OnChanges生命周期钩子接口ngOnChanges()方法来监测输入属性值的变化并做出相应处理。
组件所有输入属性的变更都会被OnChanges生命周期钩子捕获到。
这个 VersionChildComponent 会监测输入属性 major 和 minor 的变化,并把这些变化编写成日志以报告这些变化。
import { Component, Input, OnChanges, SimpleChange } from '@angular/core';@Component({selector: 'app-version-child',template: `<h3>Version {{major}}.{{minor}}</h3><h4>Change log:</h4><ul><li *ngFor="let change of changeLog">{{change}}</li></ul>`})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(', '));}}
VersionParentComponent 提供 minor 和 major 值,把修改它们值的方法绑定到按钮上。
import { Component } from '@angular/core';@Component({selector: 'app-version-parent',template: `<h2>Source code version</h2><button (click)="newMinor()">New minor version</button><button (click)="newMajor()">New major version</button><app-version-child [major]="major" [minor]="minor"></app-version-child>`})export class VersionParentComponent {major = 1;minor = 23;newMinor() {this.minor++;}newMajor() {this.major++;this.minor = 0;}}
下面是点击按钮的结果。

输出型属性
就像我们的方法一样,有输入参数,有返回值。同样,我们的组件交互也需要有返回值(即输出型属性)。通过输出型属性,我们可以就将子组件的内容反馈给父组件,从而实现从子组件到父组件的交互。
在Angular中,我们使用@Output来标识一个输出型属性,输出型属性都需要定义成EventEmitter类型。
@Output change: EventEmitter<boolean> = new EventEmitter<boolean>();
在父组件中使用 () 来绑定子组件的输出型属性:
<app-child (change)="doChange($event)"></app-child>
$event 的类型就是子组件中EventEmitter的泛型值boolean。
在子组件的中通过change属性传值:
this.change.emit(true);
这样我们的父组件中的doChange中就可以获取true值:
doChange(event: boolean) {// 此时的event就是trueconsole.log(event);}// 浏览器空时
