了解Angular的@Input()和@Output()
首先/起初/最初
有时候在业务中遇到需要实施防止多次点击按钮的解决方案的情况。因此我想着制作一个像魔法一样的按钮组件,通过使用这个组件来实现按钮,它可以自动在内部执行这种防止多次点击的策略。但是我试图实现的方法被认为是反模式,所以放弃了。
虽然有人说我只是浪费了时间,但事实并非如此,多亏了这个,我能够理解Angular中的@Input()和@Output()概念。因此,我希望能在本文中分享我对这些概念的理解和记录。
请留意以下事项
在这个例子中,我们使用了Angular-material。
另外,我们将省略在app.module.ts中声明模块的部分。
@Input()和@Output()代表了什么意思?
首先,我将简要解释这些的作用。
首先,@Input()的作用是从父组件传递值给子组件。
而@Output()的作用是从子组件传递事件(值)给父组件。
尝试用代码深入理解。
这次我们将以一个简单的按钮组件示例来解释。
首先我们看一下组件之间的父子关系。在这个例子中,调用按钮组件的那一方(比如app.component)就是父组件,而按钮组件则是子组件。
请提供输入。
按钮组件
import { Component, Input } from '@angular/core';
@Component({
selector: 'app-amazing-button',
templateUrl: './amazing-button.component.html',
styleUrls: ['./amazing-button.component.css']
})
export class AmazingButtonComponent {
@Input() buttonText: string = 'BUTTON';
@Input() buttonColor: string = '';
constructor() { }
}
<button mat-raised-button color="buttonColor">{{buttonText}}</button>
在按钮组件中,我们声明了@Input() buttonText和@Input() buttonColor。它们分别用于指定按钮的名称和颜色。
通过声明@Input()修饰的变量,我们可以将此组件作为属性从父组件调用,并将值存储在该属性中,以实现从父级到子级的值传递。
首先不指定,我们尝试从父组件调用子组件。
<app-amazing-button></app-amazing-button>
这次尝试将buttonText作为属性进行指定…
<app-amazing-button buttonText="!!AmazingButton!!"></app-amazing-button>
<app-amazing-button buttonText="!!AmazingButton!!" buttonColor="accent"></app-amazing-button>
在以下情况下,@Input()用于从父组件向子组件传递值。
@Output()装饰器
我们将继续使用”继续”按钮组件。
按钮组件
import { Component, EventEmitter, Input, Output } from '@angular/core';
@Component({
selector: 'app-amazing-button',
templateUrl: './amazing-button.component.html',
styleUrls: ['./amazing-button.component.css']
})
export class AmazingButtonComponent {
@Input() buttonText: string = 'BUTTON';
@Input() buttonColor: string = '';
@Output() addOops: EventEmitter<string> = new EventEmitter(); // 追加
constructor() { }
/**
* 追加
*/
sendText() {
this.addOops.emit('Oops!');
}
}
<!--clickイベントを追加-->
<button mat-raised-button color="{{buttonColor}}" (click)="sendText()">{{buttonText}}</button>
我已经使用@Output()和点击事件sendText()实现了addOops这个功能。
在声明@Output()时,要实例化EventEmitter。
被声明为@Output()的变量本身就是一个由父组件使用的事件,并通过接收在该事件中发出的值来实现从子组件到父组件的值传递。
在我们开始解释实际操作之前,让我们也把家长方面的实施考虑进去。
<!--子コンポーネントのイベントを追加-->
<app-amazing-button buttonText="!!AmazingButton!!" buttonColor="accent" (addOops)="logMessage($event)"></app-amazing-button>
import { Component } from '@angular/core';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
/**
* 追加
*/
logMessage(text: string) {
console.log(`${text}, Hello Angular!`);
}
}
在父组件中,您可以使用子组件中声明为@Output()的变量作为事件。
这是在app.component.html中的(addOops)=~部分。
当点击此按钮时,首先触发子组件中声明的事件。
在这种情况下,对应的事件是amazing-button.component的(click)事件。
sendText() {
this.addOops.emit('Oops!');
}
当调用名为emit()的函数时,它会将值传递给调用其父函数的地方。您可以将要传递的值作为参数传入。
子组件已经传递了值。在父组件中接收这个值的方式是。
(addOops)="logMessage($event)
子コンポーネントのイベントを受け取ることが可能になります。
logMessage(text: string) {
console.log(`${text}, Hello Angular!`);
}
当我们在组件中传递一个名为text的参数时,子组件传递的值将被赋给text,以便在父组件中使用。当我们尝试运行时,我们可以看到效果。
Oops!, Hello Angular!
并在控制台上显示。
顺便提一下,在 @Output() 中,可以使用 emit() 将数据返回为一个对象,可以返回多个数据。
尽管变得冗长了,但归纳一下@Output()的流程如下。
-
- 子组件的事件触发。
-
- 在子组件的处理中进行emit()。
- 在父组件中使用$event接收。
這是如此。
就像这样,@Output()用于将事件(值)从子组件传递给父组件。
顺便提一下
虽然@Input()、@Output()会经常被使用,但也存在着反模式。
关于反模式的详情请见这里。
Angular2的反模式集合
当使用@Input绑定对象时,会遇到各种问题【ionic】【Angular】
将对象作为@Input绑定
看起来对象将成为引用传递的方式。可能会导致意想不到的行为…。
我本来想把回调函数作为@Input()传递,但这是一个反模式?
虽然还有一种方法可以做到…
为了避免陷入回调地狱,还是不这样做为好。
Angular 2:使用事件与回调进行组件通信
最后
这个@Input()和@Output()是非常方便的功能,希望大家一定要理解。
闲聊
在Qiita上使用“@”符号会形成对账户的链接,所以有点麻烦。
请提供相关链接。
理解 Angular 的 @Output
Angular2 的反模式集
使用 @Input 绑定对象时会遇到多种问题 【Angular】
使用 @Input 绑定对象
Angular 2:使用事件与回调进行组件通信
参考阅读相关书籍…
Angular 应用程序编程