繁体   English   中英

Angular:如何将数据从子组件发送到父组件?

[英]Angular: how to send data from child component to parent component?

我正在学习 Angular。 我已经阅读了文档和五篇博文,一切都一清二楚。 我认为有两个模板。 子模板有一个按钮。 当用户单击按钮时,我希望在父模板中显示一个元素(说明卡)。 当用户再次单击按钮时,我希望该元素不显示。 即,子按钮打开和关闭父元素。

<button (click)="toggleInstructions()">Instructions</button>

在我的头(子)组件中,我制作了一个输出事件发射器sendData 、一个布尔变量showInstructions和一个在truefalse之间切换showInstructions的函数。 在记录showInstructions (效果很好!)之后,它会调用sendData来发出数据。 我创建了一个新变量myData因为我对this的使用感到困惑。

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

@Component({
  selector: 'app-header',
  templateUrl: './header.component.html',
  styleUrls: ['./header.component.css']
})
export class HeaderComponent {
  @Output() sendData = new EventEmitter<boolean>();

  showInstructions: boolean = false;

  toggleInstructions(myData: boolean) {
    console.log("Clicked!");
    switch (true) {
      case (this.showInstructions === true):
      this.showInstructions = false;
      break;

      case (this.showInstructions === false):
      this.showInstructions = true;
      break;

      default:
      console.log("Error in switch-case.");
    }
    console.log(this.showInstructions);
    myData = this.showInstructions;
    console.log(myData);
    this.sendData.emit(myData);
  }
}

在父组件中,我导入了子组件( HeaderComponent )并创建了一个函数toggledInstructions来接收数据。 当我单击按钮时,没有记录任何内容。

import { Component } from '@angular/core';
import { HeaderComponent } from './header/header.component';

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

  toggledInstructions(myData: boolean) {
    console.log("Data coming in!");
    console.log(myData);
  }
}

我很困惑这应该如何工作。 除了数据变量名称( myData )之外,我在连接发送和接收函数的文档中看不到任何内容。

谢谢你的帮助!

我发现这个 ZeroesAndOnes 博客文章很好地解释了这一点。 要解决我的答案,请从博客文章开始并启动其代码。

child.component.html更改为:

<div style="border: solid 1px gray; padding: 15px; margin-top: 15px;">
    <h2>Child Component</h2>
    <button (click)="clickButton()">Show Element in Parent</button>
</div>

子模板没有什么特别之处。 只是一个触发控制器功能的按钮。

child.component.ts更改为:

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

@Component({
  selector: 'app-child',
  templateUrl: './child.component.html',
})
export class ChildComponent {
  showElement: boolean = false;
  @Output() buttonClicked: EventEmitter<boolean> = new EventEmitter<boolean>();

  clickButton() {
    console.log("(Child) Value before toggle: " + this.showElement);
    console.log("(Child) Button clicked!");
    switch (true) {
      case (this.showElement === true):
      this.showElement = false;
      break;

      case (this.showElement === false):
      this.showElement = true;
      break;

      default:
      console.log("Error in switch-case.");
    }
    console.log("(Child) Value after toggle: " + this.showElement);
    this.buttonClicked.emit(this.showElement);
  }

}

变量列表以showElement开头,它是一个boolean并被初始化为false ,即父元素是隐藏的。

接下来是另一个变量,它是 Angular 魔法的第一位。 变量是buttonClicked并且它有装饰器@Output() 这个装饰器意味着该变量将在控制器之外可用。 该变量的类型为EventEmitter<boolean>并且它被分配了一个新的事件发射器。 如果您喜欢较短的行,则可以省略该类型:

@Output() buttonClicked = new EventEmitter<boolean>();

接下来是在truefalse之间切换showElement的函数。 在这个函数的底部是 Angular 魔法的第二位。 调用输出事件并发送showElement变量以由事件发射器发射。

现在将父模板app.component.html更改为:

<div style="border: solid 1px gray; padding: 15px;">
  <app-child (buttonClicked)="parentEventHandlerFunction($event)">
  </app-child>
  
  <h1>Parent Component</h1>
  <span><b>Value emitted from child component is:</b></span>
  {{ valueEmittedFromChildComponent }}
  
  <div *ngIf="valueEmittedFromChildComponent"><span style="color: red;"><b>My awesome element!</b></span>
  </div>
  
</div>

Angular 的大魔法在父模板中,特别是在这一行中:

  <app-child (buttonClicked)="parentEventHandlerFunction($event)">
  </app-child>

指令app-child将子模板嵌入到父模板中。 buttonClicked是子控制器中的事件发射器。 parentEventHandlerFunction是父控制器中的一个函数。 $event是从孩子发送给父母的对象。 这一行将子控制器和父控制器的部分组合在一起,用等号将它们连接起来。 这就是 Angular 的巨大魔力。

现在设置父控制器app.component.ts

import { Component } from '@angular/core';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
})
export class AppComponent {
  valueEmittedFromChildComponent: boolean;

  parentEventHandlerFunction(valueEmitted){
    this.valueEmittedFromChildComponent = valueEmitted;
    console.log("(Parent) Value emitted: " + valueEmitted);
  }
}

我们有一个名为valueEmittedFromChildComponent变量,它是一个boolean 然后我们有一个函数parentEventHandlerFunction和一个参数valueEmitted $event对象来自父模板中的魔法线,并分配给局部变量valueEmittedFromChildComponent

回到父模板,我们显示局部变量valueEmittedFromChildComponent并在*ngIf使用它来显示和隐藏元素。

ZeroesAndOne 总结了他们的博客文章,“总而言之,Angular 可以非常轻松地创建使用 @Output() 装饰器向其父组件发送数据的子组件。” 哈! 这不是我所说的“极其容易”。 相比之下,在 AngularJS 中,两个模板将共享一个控制器。 一个模板中的按钮绑定到控制器中的一个函数,该函数切换一个变量,该变量绑定到第二个模板中的元素以显示和隐藏元素。 数据从第一个模板到控制器中的单个变量再到第二个模板。 这“非常容易”。

在 Angular 中,子模板中的按钮会触发子控制器中的一个函数,与 AngularJS 相同。 但是随后您需要使用事件发射器制作一个@Output()装饰器,并从切换函数中调用事件发射器。 然后数据被发送到父模板中的魔术线,它结合了来自子控制器和父控制器的东西。 然后数据进入父控制器,然后返回父模板以显示或隐藏目标元素。

让我们重复一遍。 当用户单击子模板中的按钮时,数据进入子控制器,在那里函数切换值,然后将数据从函数发送到事件发射器。 事件发射器将数据发送到父模板,父模板将数据发送到父控制器,父控制器将数据发送回父模板以显示或隐藏元素。 这不是我所说的容易。

你会如何在 React 中做到这一点? React 更像 AngularJS 还是 Angular?

看起来您需要$event变量来获取发出的值:

<button (click)="toggleInstructions($event)">Instructions</button>

toggledInstructions(event: boolean) {
    console.log("Data coming in!", myData);
}

事件绑定(fooevent)允许绑定到 DOM 事件和EventEmitter事件

更新:

工作代码示例:

ChildComponent.ts:

@Output() public onFooClicked = new EventEmitter<boolean>();

showMenu() {
  this.onFooClicked .emit(true);
}

app.component.ts:

<foo (onFooClicked)="onClicked($event)">
</foo>

onClicked(event: boolean) {
    console.log(`Somebody clicked`, event);
}

此外,还有一篇很棒的文章如何传递数据。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM