使用输入和输出属性在组件之间进行通信
介绍
Angular 中组件之间的通信将帮助您将数据从子组件传递到父组件,反之亦然。
使用输入绑定将数据从父组件传递到子组件
当我们想要将数据从父组件传递到子组件时,我们使用带有@Input 装饰的输入绑定。
让我们考虑一个例子,其中 PersonChildComponent 有两个带有 @Input 修饰的输入属性。正如我们在下面的例子中看到的,我们必须从 '@angular/core' 库导入 Input。
文件名: personchild.component.ts
      import { Component, Input } from '@angular/core';
 
import { Person } from './Person';
 
@Component({
  selector: 'app-person-child',
  template: `
    <h3>{{person.name}} says:</h3>
    <p>I, {{person.name}}, welcome to Pluralsight, {{masterName}}.</p>
  `
})
export class PersonChildComponent {
  @Input() person: Person;
  @Input('master') masterName: string;
}
    
我们可以使用 @Input 绑定的别名。如上例所示,masterName 的别名是 master。
使用 Setter 和 ngOnChanges() 拦截输入属性的改变
拦截输入属性有助于根据来自父级的值采取行动。
使用 setter 进行更改:
让我们考虑一个例子,我们在子 PersonChildComponent 中设置输入属性的 personname,该子组件会从名称中修剪空格并用默认文本替换空值。
下面的 PersonParentComponent 演示了人名中的名称变化,包括全带空格的人名。
文件名: personchild.component.ts
      import { Component, Input } from '@angular/core';
 
@Component({
  selector: 'app-personname-child',
  template: '<h3>"{{personname}}"</h3>'
})
export class PersonChildComponent {
  private _personname = '';
 
  @Input()
  set personname(personname: string) {
    this._personname = (personname && personname.trim()) || '<no personname set>';
  }
 
  get personname(): string { return this._personname; }
}
    
文件名: personparent.component.ts
      import { Component } from '@angular/core';
 
@Component({
  selector: 'app-person-parent',
  template: `
  <h2>Master have {{personnames.length}} personnames</h2>
  <app-person-child *ngFor="let personname of personnames" [personname]="personname"></app-person-child>
  `
})
export class PersonParentComponent {
  // Displays 'Yallaling', '<no person set>', 'Goudar'
  personnames = ['Yallaling', '   ', '  Goudar  '];
}
    
ngOnChanges() 的变化:
OnChanges 生命周期钩子接口的 ngOnChanges() 方法可检测输入属性值的更改并采取行动。在监视多个交互的输入属性时,您可能更喜欢此方法而不是属性设置器。
让我们考虑一个例子,其中我们有 MinmaxChildComponent,它检测最小和最大输入属性的变化并编写报告这些变化的日志消息。
文件名: minmaxchild.component.ts
      import { Component, Input, OnChanges, SimpleChange } from '@angular/core';
@Component({
  selector: 'app-minmax-child',
  template: `
    <h3>Min value: {{minimum}} Max value: {{maximum}}</h3>
    <h4>Change log:</h4>
    <ul>
      <li *ngFor="let change of changeLog">{{change}}</li>
    </ul>
  `
})
export class MinmaxChildComponent implements OnChanges {
  @Input() minimum: number;
  @Input() maximum: 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(', '));
  }
}
    
MinmaxChildComponent 提供最小值和最大值,并将按钮绑定到改变它们的方法。
文件名: minmaxparent.component.ts
      import { Component } from '@angular/core';
@Component({
  selector: 'app-minmax-parent',
  template: `
    <h2>Source code minmax</h2>
    <button (click)="changedMin()">New minimum value</button>
    <button (click)="changedMax()">New minmax value</button>
    <app-minmax-child [major]="major" [minor]="minor"></app-minmax-child>
  `
})
export class MinmaxParentComponent {
  minimum = 1;
  maximum = 23;
  changedMin() {
    this.minimum++;
  }
  changedMax() {
    this.maximum++;
    this.minimum = 0;
  }
}
    
当我们点击“新最小值”按钮时,最小值将会增加;当我们点击“新最大值”按钮时,最大值将会增加。我们可以看到更改的值已记录在更改日志中。
使用输出绑定将数据从子级传递到父级
Output 是一个使用 @Output 装饰器注释的可观察属性,该属性始终返回 Angular EventEmitter。值作为与事件绑定绑定的事件从组件流出。
在 Angular 中,组件可以使用 @Output 和 EventEmitter 发出事件。两者都是 @angular/core 的一部分。
让我们考虑一个例子,其中我们从组件 ExampleChildComponent 发出总和值。
文件名:examplechild.component.ts
      import { Component, EventEmitter, Output } from '@angular/core';
@Component({
    selector: 'app-example-child',
    template: `<button class='btn btn-primary' (click)="changeValue()">Click me</button> `
})
export class ExampleChildComponent {
    @Output() valueChange = new EventEmitter();
    sum = 0;
    changeValue() { 
        // You can give any function name
        this.sum = this.sum + 10;
        this.valueChange.emit(this.sum);
    }
}
    
让我们考虑一个示例,我们将发出一个事件并将一个参数传递给该事件。在下面的示例中,我们将从 ExampleChildComponent 向 ExampleComponent 发出一个值。显示来自 ExampleChildComponent 的总值。
文件名:example.component.ts
      import { Component, OnInit } from '@angular/core';
@Component({
    selector: 'app-example',
    template: `<app-example-child (changeValue)='displaySum($event)'></app-example-child>`
})
export class ExampleComponent implements OnInit {
    ngOnInit() {
    }
    displaySum(sum) {
        console.log(sum);
    }
}
    
结论
在本指南中,我们探索了 Angular 中的输入和输出属性技术。我们还了解了将值从父组件传递到子组件以及反之亦然的不同方法或方式。
您可以在我的指南《Angular 中的属性、类和样式绑定》中了解有关 Angular 绑定的更多信息。
免责声明:本内容来源于第三方作者授权、网友推荐或互联网整理,旨在为广大用户提供学习与参考之用。所有文本和图片版权归原创网站或作者本人所有,其观点并不代表本站立场。如有任何版权侵犯或转载不当之情况,请与我们取得联系,我们将尽快进行相关处理与修改。感谢您的理解与支持!
                                
                                    
                                    
                                    
                                    
                                    
                                    
                                    
                                    
                                    
                                    
                                    
                                    
                                    
                                    
                                    
                                    
                                    
                                    
                                    
                                    
                                    
                                
                            
                                    
                                    
                                    
                                    
    
    
            
  
        
请先 登录后发表评论 ~