一般而言,我們可以透過在 children component 上使用 @Ouput 修飾詞與 EventEmitter 類別,來將事件傳給 parent component,並且可以在 template file 上使用 (someEvent)="someEventHandler($event)"
這種繫結的方式來處理事件。方便歸方便,不過這種方法不能夠直接用在一般原生的 HTMLElement 物件上,若想在原生 HTMLElement 物件使用自己定義的事件的話,可以透過 Angular 的 Dependency Injection 來完成!
這也就是今天要介紹的 Tip:透過 EVENT_MANAGER_PLUGINS
DI Token 來提供自定義的事件!
export class EchoEvent {
manager!: EventManager;
supports(eventName: string): boolean {
return eventName === 'echo';
}
addEventListener(
element: HTMLElement,
eventName: string,
handler: (event: Event) => void
): () => void {
element.addEventListener('echo', (e) => {
console.log(`⚡: EchoEvent -> e`, e);
});
return () => {
element.removeEventListener('echo', handler);
};
}
}
↑ Block 1
providers: [
{
provide: EVENT_MANAGER_PLUGINS,
useClass: EchoEvent,
multi: true
}
]
↑ Block 2
要使用今天的 Tip,只需要透過兩個步驟:
首先要先像 Block 1 一樣,建立一個之後要拿來當作 factory 的類別。且該類別必須要實作 EventManagerPlugin
類別。
不過目前 Angular 沒有 export EventManagerPlugin 這個類別,而且從 2017 年就有人開 issue 到現在還沒處理。而在另一個 PR 中有另一個 Contributor 提到,他認為可以使用
Renderer2
來處理事件就好(link)。
在 module 中加入 EVENT_MANAGER_PLUGINS
這個 DI Token 的 provider。
multi: true
。好!就這樣!
接下來就可以像使用一般原生事件一樣來使用剛剛建立的事件了:
<div (echo)="handler()"></div>
↑ Block 3
在瀏覽器內手動觸發 div
元素的 echo
事件:
圖中的 console.log 並不是由 div 的 handler 所產生的,而是由 Block 1 的程式碼產生的行為。
雖然 EchoEvent 有個 addEventListener 方法,但千萬不要被它騙到,因為實際上 Angular 背後只會「執行」這個方法,並不會幫你將自訂的事件加到 element 的 event listener 內,你必須要自己處理!
之後就可以像 Block 3 一樣在原生的 HTMLElement 上,使用事件繫結的方式來使用自定義的事件囉!
以下按照入團順序列出我們團隊夥伴的系列文章!
好酷的功能,雖然想不到應用情境,但學習到了!!
就是酷而已!(
我想了一下,應該滿適合用在一些所有元素都有機會使用的這種事件上,就不用另外針對每個元素去新增 EventListener,只需要給 handler 就可以了。
我只想得到 WebComponents XD