[英]Angular: how to send data from child component to parent component?
我正在学习 Angular。 我已经阅读了文档和五篇博文,一切都一清二楚。 我认为有两个模板。 子模板有一个按钮。 当用户单击按钮时,我希望在父模板中显示一个元素(说明卡)。 当用户再次单击按钮时,我希望该元素不显示。 即,子按钮打开和关闭父元素。
<button (click)="toggleInstructions()">Instructions</button>
在我的头(子)组件中,我制作了一个输出事件发射器sendData
、一个布尔变量showInstructions
和一个在true
和false
之间切换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>();
接下来是在true
和false
之间切换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.