组件通讯
向组件内部传递数据
Input 装饰器
<app-favorite [isFavorite]="true"></app-favorite>
// favorite.component.ts
import { Input } from '@angular/core';
export class FavoriteComponent {
@Input() isFavorite: boolean = false;
}
注意:在属性的外面加 []
表示绑定动态值,对于布尔类型,不加 []
表示绑定普通值,例如 true
在组件内接收后是字符串 "true"
。
<app-favorite [is-Favorite]="true"></app-favorite>
import { Input } from '@angular/core';
export class FavoriteComponent {
@Input("is-Favorite") isFavorite: boolean = false
}
属性别名
通过给 @Input()
装饰器传递参数,可以重命名属性。
import { Component, Input } from '@angular/core';
@Component({
selector: 'app-child',
template: `<p>{{ myValue }}</p>`,
})
export class ChildComponent {
@Input('parentValue') myValue!: string; // 父组件使用 "parentValue" 绑定
}
父组件:
<app-child [parentValue]="'Hello'"></app-child>
使用别名可以避免某些属性名可能与 DOM 属性或全局对象名称冲突。例如:
@Component({
selector: 'app-child',
template: `<p>{{ id }}</p>`,
})
export class ChildComponent {
@Input('customId') id!: string; // 避免与 DOM 的 id 属性冲突
}
booleanAttribute
@Input
装饰器可以传入参数 {transform: booleanAttribute}
,用于将字符串类型的布尔属性(HTML 属性中传递的布尔值通常是字符串)转换为真正的 JavaScript 布尔值的机制。
用途:
在 HTML 中,布尔属性(如 disabled
, checked
, readonly
)如果存在,则会被解析为字符串,即使没有显式赋值。例如:
<input disabled />
disabled
属性的值在 JavaScript 中是 "true"
,而不是一个真正的布尔值 true
。{transform: booleanAttribute}
可以自动将这种字符串值转换为布尔值。
示例:
import { Component, Input } from '@angular/core';
@Component({
selector: 'app-boolean-example',
template: `<p>The button is {{ disabled ? 'Disabled' : 'Enabled' }}</p>`,
})
export class BooleanExampleComponent {
@Input({ transform: booleanAttribute }) disabled = false; // 默认为 false
}
父组件:
<app-boolean-example disabled></app-boolean-example>
- 在父组件中传递
disabled
,即使不显式赋值,它也会被识别为true
。 - 如果未传递
disabled
属性,子组件中的disabled
属性值会保留默认值false
。
向组件外部传递数据
Output 装饰器
<!-- 子组件模板 -->
<button (click)="onClick()">click</button>
// 子组件类
import { EventEmitter, Output } from "@angular/core"
export class FavoriteComponent {
@Output() change = new EventEmitter()
onClick() {
this.change.emit({ name: "张三" })
}
}
<!-- 父组件模板 -->
<app-favorite (change)="onChange($event)"></app-favorite>
// 父组件类
export class AppComponent {
onChange(event: { name: string }) {
console.log(event)
}
}
父组件与子组件通过本地变量互动
父组件不能使用数据绑定来读取子组件的属性或调用子组件的方法。但可以在父组件模板里,新建一个本地变量来代表子组件,然后利用这个变量来读取子组件的属性和调用子组件的方法:
子组件 CountdownTimerComponent
:
@Component({
selector: 'app-countdown-timer',
template: '<p>{{message}}</p>'
})
export class CountdownTimerComponent implements OnDestroy {
intervalId = 0;
message = '';
seconds = 11;
ngOnDestroy() { this.clearTimer(); }
start() { this.countDown(); }
stop() {
this.clearTimer();
this.message = `Holding at T-${this.seconds} seconds`;
}
private clearTimer() { clearInterval(this.intervalId); }
private countDown() {
// ...
}
}
父组件 CountdownLocalVarParentComponent
:
@Component({
selector: 'app-countdown-parent-lv',
template: `
<h3>Countdown to Liftoff (via local variable)</h3>
<button type="button" (click)="timer.start()">Start</button>
<button type="button" (click)="timer.stop()">Stop</button>
<div class="seconds">{{timer.seconds}}</div>
<app-countdown-timer #timer></app-countdown-timer>
`,
styleUrls: ['../assets/demo.css']
})
export class CountdownLocalVarParentComponent { }
父组件不能通过数据绑定使用子组件的 start
和 stop
方法,也不能访问子组件的 seconds
属性。把本地变量(#timer
)放到(<countdown-timer>
)标签中,用来代表子组件。这样父组件的模板就得到了子组件的引用,可以在父组件的模板中访问子组件的属性和方法。
最后更新于