组件通讯
向组件内部传递数据
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>)标签中,用来代表子组件。这样父组件的模板就得到了子组件的引用,可以在父组件的模板中访问子组件的属性和方法。
最后更新于