iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 9
1
Modern Web

從巨人的 Tip 看 Angular系列 第 9

[Day 9] 事件繫結好方便,那你知道 EVENT_MANAGER_PLUGINS 嗎?

  • 分享至 

  • xImage
  •  

一般而言,我們可以透過在 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,只需要透過兩個步驟:

  1. 首先要先像 Block 1 一樣,建立一個之後要拿來當作 factory 的類別。且該類別必須要實作 EventManagerPlugin 類別。

    不過目前 Angular 沒有 export EventManagerPlugin 這個類別,而且從 2017 年就有人開 issue 到現在還沒處理。而在另一個 PR 中有另一個 Contributor 提到,他認為可以使用 Renderer2 來處理事件就好(link)。

  2. 在 module 中加入 EVENT_MANAGER_PLUGINS 這個 DI Token 的 provider。

    1. Block 2 範例是用 useClass 的方式來建立實體。
    2. 切記要記得加上 multi: true

好!就這樣!

接下來就可以像使用一般原生事件一樣來使用剛剛建立的事件了:

<div (echo)="handler()"></div>

↑ Block 3

在瀏覽器內手動觸發 div 元素的 echo 事件:

https://ithelp.ithome.com.tw/upload/images/20200924/20129148RYdrRGSiUm.png

圖中的 console.log 並不是由 div 的 handler 所產生的,而是由 Block 1 的程式碼產生的行為。

雖然 EchoEvent 有個 addEventListener 方法,但千萬不要被它騙到,因為實際上 Angular 背後只會「執行」這個方法,並不會幫你將自訂的事件加到 element 的 event listener 內,你必須要自己處理!

之後就可以像 Block 3 一樣在原生的 HTMLElement 上,使用事件繫結的方式來使用自定義的事件囉!

第 9 天啦 ?

以下按照入團順序列出我們團隊夥伴的系列文章!


上一篇
[Day 8] 所以我說那個 multi 是?
下一篇
[Day 10] 深度看一下 Angular 建立 multi provider 的機制
系列文
從巨人的 Tip 看 Angular30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

1 則留言

0
黃升煌 Mike
iT邦研究生 5 級 ‧ 2020-09-24 14:30:51

好酷的功能,雖然想不到應用情境,但學習到了!!
/images/emoticon/emoticon41.gif

就是酷而已!(
我想了一下,應該滿適合用在一些所有元素都有機會使用的這種事件上,就不用另外針對每個元素去新增 EventListener,只需要給 handler 就可以了。

我只想得到 WebComponents XD

我要留言

立即登入留言