在用@Input装饰器为Angular中的组件传值中,给大家介绍了如何通过@Input装饰器向组件(Component)传递参数,在本文中将会给大家介绍如何自定义组件的事件,如何响应事件,又如何通过事件来接收数据。
定义自定义事件
假设我们正在开发一个个人待办事项管理的应用,其中我们定义一个TodoComponet, 职责是在在界面上显示、编辑一个代办事项(Todo)。如何给这个组件传值,我们已经在文章用@Input装饰器为Angular中的组件传值中为大家介绍了,那如果TodoComponent想要抛出一个事件,比如当删除一个Todo的时候,需要通知其它组件自己被删除了,这该怎么做呢?在Angular中,可以使用@Output装饰器来为组件声明一个可以抛出的事件,也就是我们常说的为组件添加一个自定义事件。让我们来看代码
组件类定义文件: todo.component.ts
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| @Component({ selector: 'app-todo', templateUrl: './todo.component.html', styleUrls: ['./todo.component.css'] }) export class TodoComponent implements OnInit {
@Output() deleteEvent = new EventEmitter();
constructor() { }
ngOnInit() { }
onDelete() { this.deleteEvent.next(); } }
|
从组件类代码的定义我们可以看到,自定义事件的定义要使用到一个装饰器 - @Output 和一个类 EventEmitter。在上面的代码中,我们通过声明一个属性的方式来声明一个自定义事件,属性名就是事件名。
组件模板文件: todo.component.html
1 2 3 4 5 6 7 8 9 10 11 12
| <div class="card"> <div class="card-head"> {{todo.title}} </div> <div class="card-content"> {{todo.desc}} {{todo.done}} </div> <div class="card-footer"> <button (click)="onDelete()">Delete</button> </div> </div>
|
在组件的模板代码中,我们增加了一个Delete按钮并绑定了一个onDelete的函数作为按钮按下时的响应函数,模拟删除的动作。结合两部分的代码我们可以看到,当用户按下Delete时,会执行this.deleteEvent.next()把定义的事件抛出去(触发)。我们再来看看使用Todo组件的代码
页面模板代码: todo-page.component.html
1 2 3
| <div *ngFor = "let todo of todos"> <app-todo [todo]="todo" (deleteEvent)="onDeleteEvent()"></app-todo> </div>
|
在模板代码中,我们通过()将自定义事件 - deleteEvent绑定到函数onDeleteEvent()上。函数在对应的类代码中定义
页面类代码: todo-page.component.ts
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| @Component({ selector: 'app-todo-page', templateUrl: './todo-page.component.html', styleUrls: ['./todo-page.component.css'] }) export class TodoPageComponent implements OnInit {
todos: Todo[];
constructor() {}
ngOnInit() { }
onDeleteEvent() { console.log('onDeleteEvent..'); } }
|
运行程序后,当Todo组件中的Delete按钮被按下,我们可以在浏览器的Javascript控制台看到’onDeleteEvent..’被输出出来。这样就完成了组件自定义事件的定义,触发和处理。
在自定义事件中传参
在Angular中,为自定义事件传递参数非常简单,直接在触发事件调用”next”函数时,带上参数就可以了。比如在我们的例子中,我们希望在自定义事件中把当前的Todo项作为事件参数传出去,就可以简单的调用”next(this.todo)”。修改后的代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| @Component({ selector: 'app-todo', templateUrl: './todo.component.html', styleUrls: ['./todo.component.css'] }) export class TodoComponent implements OnInit {
@Input() todo: Todo;
@Output() deleteEvent = new EventEmitter();
constructor() { }
ngOnInit() { }
onDelete() { this.deleteEvent.next(this.todo); }
}
|
注意第20行,next函数调用的参数
在接收时,需要使用Angular中的一个特别变量: 1 2 3
| <div *ngFor = "let todo of todos"> <app-todo [todo]="todo" (deleteEvent)="onDeleteEvent($event)"></app-todo> </div>
|
注意第2行代码,\]">event变量的使用
页面类代码: todo-page.component.ts
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| @Component({ selector: 'app-todo-page', templateUrl: './todo-page.component.html', styleUrls: ['./todo-page.component.css'] }) export class TodoPageComponent implements OnInit {
todos: Todo[];
constructor() {}
ngOnInit() { }
onDeleteEvent(event) { console.log('onDeleteEvent..'); console.log('Event data = ' + JSON.stringify(event)); } }
|
注意第16行开始的onDeleteEvent函数