@Output() 和 EventEmitter
概述
在 Angular 中,@Output()
裝飾器和 EventEmitter
類別是實現子組件向父組件傳遞資料的主要機制。這個機制類似於 Vue 中的 $emit
。
基本用法
在子組件中定義輸出的事件:
import {Component, Output, EventEmitter} from '@angular/core';
@Component({
selector: 'app-child',
styles: `.btn { padding: 5px; }`,
template: `
<button class="btn" (click)="addItem()">Add Item</button>
`,
standalone: true,
})
export class ChildComponent {
// 定義一個輸出事件,型別是 EventEmitter<string>
@Output() addItemEvent = new EventEmitter<string>()
// 當按鈕被點擊時調用此方法
addItem() {
// 發射一個烏龜表情符號事件
this.addItemEvent.emit('🐢');
}
}
在父組件中接收事件:
import {Component} from '@angular/core';
import {ChildComponent} from './child.component';
@Component({
selector: 'app-root',
template: `
<!--
使用子組件 app-child
(addItemEvent) 監聽子組件發出的事件
$event 是子組件發出的數據,這裡是 🐢
addItem() 是處理事件的方法
-->
<app-child (addItemEvent)="addItem($event)" />
<p>🐢 all the way down {{ items.join(' ') }}</p>
`,
standalone: true,
imports: [ChildComponent],
})
export class AppComponent {
items: string[] = [];
// 定義添加項目的方法
// 參數 item 是從子組件接收到的字串(🐢表情符號)
addItem(item: string) {
this.items.push(item);
}
}
以下 AI 提供
EventEmitter 詳解
建立 EventEmitter
typescriptCopy// 指定發射值的類型
@Output() numberEvent = new EventEmitter<number>();
@Output() objectEvent = new EventEmitter<{id: number, name: string}>();
@Output() anyEvent = new EventEmitter<any>(); // 不建議使用 any
EventEmitter 的主要方法
emit(value)
: 發射一個事件subscribe()
: 訂閱事件unsubscribe()
: 取消訂閱pipe()
: 用於串接 RxJS 操作符
最佳實踐
命名慣例
// 建議的命名方式
@Output() valueChange = new EventEmitter<string>(); // 值改變
@Output() submit = new EventEmitter<void>(); // 動作
@Output() statusUpdate = new EventEmitter<Status>(); // 狀態更新
型別安全
// 定義介面
interface UserData {
id: number;
name: string;
}
// 使用介面作為型別
@Output() userSelect = new EventEmitter<UserData>();
事件處理
@Component({
template: `
<!-- 直接處理 -->
<app-child (dataEvent)="handleData($event)"></app-child>
<!-- 使用範本參考變數 -->
<app-child (dataEvent)="data = $event" #child></app-child>
<p>{{ data }}</p>
`
})
進階用法
多值發射
@Output() multiData = new EventEmitter<{name: string, age: number}>();
sendMultiData() {
this.multiData.emit({
name: 'John',
age: 30
});
}
事件別名
@Output('customName') originalName = new EventEmitter<string>();
與 RxJS 整合
@Output() searchEvent = new EventEmitter<string>();
// 在父組件中
<app-search (searchEvent)="onSearch($event)"></app-search>
onSearch(term: string) {
this.searchEvent
.pipe(
debounceTime(300),
distinctUntilChanged()
)
.subscribe(value => {
// 處理搜尋邏輯
});
}
與 Vue $emit 的對比
Angular:
@Output() userEvent = new EventEmitter<string>();
this.userEvent.emit('data');
Vue:
this.$emit('user-event', 'data');
主要差異:
Angular 需要明確宣告和型別定義
Angular 使用 EventEmitter 類別
Vue 直接使用 $emit 方法
Angular 提供更多型別安全性
Last updated