这个 Angular 5 示例如何处理父组件和子组件之间的通信?

How exactly works this Angular 5 example handling comunication between a parent and child component?

我从 Angular 开始,我对这个与父组件和子组件之间的通信相关的示例究竟如何工作有一些疑问。

所以我有这个父组件。该组件用于显示项目列表(每个项目都由子组件表示)。与此组件交互,我可以在此项目列表中添加和删除项目。

这是父组件:

@Component({
  selector: 'app-products',
  templateUrl: './products.component.html'
})
export class ProductsComponent {

  productName = 'A Book';
  isDisabled = true;

  products = ['A Book', 'A Tree'];

  constructor() {

    setTimeout(
      () => {
        this.isDisabled = false;
      }, 3000)
  }


  onAddProduct() {
    this.products.push(this.productName);

  }

  onRemoveProduct(productName: string) {
    this.products = this.products.filter(p => p !== productName);
  }

}

这是它的模板:

<h1>My Products</h1>

<input *ngIf="!isDisabled" type="text" [(ngModel)]="productName">

<button *ngIf="!isDisabled" (click)="onAddProduct()">Add Product</button>

<app-product
    (productClicked)="onRemoveProduct(product)"
    *ngFor="let product of products"
    [productName]="product">
</app-product>

然后我让子组件代表父组件处理的列表中的单个项目。这是子组件:

@Component({
  selector: 'app-product',
  templateUrl: './product.component.html',
  styleUrls: ['./product.component.css']
})
export class ProductComponent {

  @Input() productName: string;

  @Output() productClicked = new EventEmitter();

  onClicked() {
    this.productClicked.emit();
  }

}

这是儿童模板:

<article class="product" (click)="onClicked()">
  <div>{{ productName }}</div>
  <p>An awesome product!</p>
</article>

好的,现在我对这两个组件如何相互作用有一些疑问:

在父组件模板中:

<app-product
    (productClicked)="onRemoveProduct(product)"
    *ngFor="let product of products"
    [productName]="product">
</app-product>

指的是子组件(由 app-product 标记)。

在我看来,基本上我是在迭代父组件 class(字符串数组)中定义的 products 列表,并且这些字符串中的每一个被传递给子组件 class 中定义的 productName 变量,为此我在子组件 class 中的这个 属性 上使用 @Input() 装饰器:

@Input() productName: string;

基本上这个 @Input() 装饰器在每次迭代时将父组件 "inject" 值赋给子组件 属性。

是吗?还是我错过了什么?

然后我有处理从项目列表中删除项目的行为:当单击列表的元素时(由子组件实现)。此元素已从列表中删除(因此从页面中删除)。

它是如何工作的(我的想法):

每个元素在子组件视图中由以下代码表示:

<article class="product" (click)="onClicked()">
  <div>{{ productName }}</div>
  <p>An awesome product!</p>
</article>

当一个对象被点击时,它会在子组件 class 中执行 onClicked() 事件。我无法直接从子组件 class 中删除所选对象,因为项目数组已定义到父组件 class 中。所以这个方法发出一个事件:

  onClicked() {
    this.productClicked.emit();
  }

有 "type" productClicked(它是事件类型还是什么?)。父组件视图中收到此事件:

(productClicked)="onRemoveProduct(product)"

调用 onRemoveProduct(product) 方法从数组中删除具有此名称的对象。

它是正确的还是在我的推理中我遗漏了什么?

还有一个疑惑是:这样处理事件和这种情况是不是一种简洁正确的处理方式?

两种情况你都对!

并且根据 angular guide,这是处理 parent/child 组件之间通信的正确方法。