Angular 2 关于自定义事件绑定的教程到底是如何工作的?

How exactly works this Angular 2 tutorial about custom event binding?

我是 Angular 2 的绝对初学者,我对我正在学习的关于 "binding to custom events".[= 的教程示例有一些疑问17=]

所以我有这个视图的主要组件 app.component.html:

<div class="container">
  <app-cockpit
    (serverCreated)="onServerAdded($event)"
    (blueprintCreated)="onBlueprintAdded($event)">
  </app-cockpit>
  <hr>
  <div class="row">
    <div class="col-xs-12">
      <app-server-element
        *ngFor="let serverElement of serverElements"
        [srvElement]="serverElement"></app-server-element>
    </div>
  </div>
</div>

在此视图中定义了包含 子组件,该子组件在前一个主视图中包含此子视图,cockpit.component.html 文件内容:

<div class="row">
  <div class="col-xs-12">
    <p>Add new Servers or blueprints!</p>
    <label>Server Name</label>
    <input type="text" class="form-control" [(ngModel)]="newServerName">
    <label>Server Content</label>
    <input type="text" class="form-control" [(ngModel)]="newServerContent">
    <br>
    <button
      class="btn btn-primary"
      (click)="onAddServer()">Add Server</button>
    <button
      class="btn btn-primary"
      (click)="onAddBlueprint()">Add Server Blueprint</button>
  </div>
</div>

包含 2 个提交表单的按钮。

这里是第一个疑问,根据我的理解,做这样的事情:

(click)="onAddServer()

意思是:"when the click event happen, perform the onAddServer() method defined into the controller of this view".

所以,进入 coockpit.component.ts class 我有:

import {Component, EventEmitter, OnInit, Output} from '@angular/core';

@Component({
  selector: 'app-cockpit',
  templateUrl: './cockpit.component.html',
  styleUrls: ['./cockpit.component.css']
})
export class CockpitComponent implements OnInit {

  /*
    EvebtEmitter è un oggetto del framework Angular che permette di emettere i nostri custom events
    @Output() decorator usato per passare qualcosa fuori dal component
   */
  @Output() serverCreated = new EventEmitter<{serverName: string, serverContent: string}>();
  @Output() blueprintCreated = new EventEmitter<{serverName: string, serverContent: string}>();

  newServerName = '';
  newServerContent = '';


  constructor() { }

  ngOnInit() {
  }

  onAddServer() {
    this.serverCreated.emit({serverName: this.newServerName, serverContent: this.newServerContent});
  }

  onAddBlueprint() {
    console.log('INTO onAddBluePrint()');
    this.blueprintCreated.emit({serverName: this.newServerName, serverContent: this.newServerContent});
  }

}

应该是这样工作的:

newServerNamenewServerContent 变量包含用户在表单中插入的数据,因为这些变量被 [(ngModel)] 指令:

<input type="text" class="form-control" [(ngModel)]="newServerName">
<input type="text" class="form-control" [(ngModel)]="newServerContent">

当用户单击 添加服务器 按钮时,将执行 onAddServer() 方法并使用 事件serverNameserverContent 内容在外部发出:

this.serverCreated.emit({serverName: this.newServerName, serverContent: this.newServerContent});

那么一个疑问就是:事件到底是什么?在我看来,这是一个包含一些信息的简单 Json 对象。

那么第二个疑问是:serverCreated 事件是由这个控制器向外部发出的,因为它是使用 @Output()装饰师。

默认收件人是什么?在我看来,这是父组件的控制器,因为在我的 app.component.ts class 中,我有处理此事件的方法:

onServerAdded(serverData: {serverName: string, serverContent: string}) { this.serverElements.push({ 类型:'server', 姓名:serverData.serverName, 内容:serverData.serverContent }); }

具体是什么意思:

就像我说的,在主组件的视图中我是说app-cockpit组件将这些事件抛给父组件。

是我的推理正确还是我遗漏了什么?所以这意味着我只能使用这种策略将事件从子组件传递到父组件或者我可以做相反的事情(从父到子,我不知道这是否是一个真实的用例场景)。

你的推理基本上是对的。

专门针对您的疑惑:

1) 当你发出一个事件时,例如在你的情况下通过 this.serverCreated.emit() 方法调用,你可以将任何对象作为 emit() 方法的参数传递,因此也是一个纯 javascript Json 对象。您可以传递任何其他您可以定义为 Typescript class 实例的对象以及任何原始类型,例如字符串或数字

2) 用@Output() 装饰器定义的事件可以被父组件监听,因此被用作允许子组件与其父组件对话的机制。父组件可以通过对称的@Input() 机制将参数传递给它们的子组件。

您可以在 https://angular.io/guide/component-interaction

获得组件相互通信的完整方法列表