UIEventObserverという同じ要素への同じイベントを貼る addEventListener を1つにまとめるライブラリを書きました。

インストール

npmで入ります。

npm install ui-event-observer

1つにまとめる?

Reactなどのコンポーネント志向のライブラリを使っていると、各コンポーネントで同じ要素へ同じイベントを貼っていることがあります。

// Component A
const handlerA = (event) => {}; 
window.addEventListener('scroll', handlerA);
// Component B
const handlerB = (event) => {};
window.addEventListener('scroll', handlerB);

UIEventObserverでは同じ事が、内部的に一つのwindow.addEventListener('scroll', ...)にまとめてられます。 (Pub/SubはEventEmitterが代わりにやる感じです)

// singleton
const eventObserver = require("ui-event-observer");
// シングルトンじゃない方法
// require("ui-event-observer").UIEventObserver
// Component A
const handlerA = (event) => {}; 
eventObserver.subscribe(window, "scroll", handlerA);
// Component B
const handlerB = (event) => {};
eventObserver.subscribe(window, "scroll", handlerB);

Example projectでは100個の"scroll"イベントをwindowに貼っています。

addEventListener vs, UIEventObserver

  • Left: 100x addEventListener
  • Right: 1 UIEventObserver

とlistenしてるイベントの数が100個以上から10個程度に減っていることが分かります。

EventTarget.addEventListenerはbubblingやcapturing、それらを止められるpreventDefault()stopPropagation()などEventEmitterに比べると高機能です。 Passive Event Listenersとかもその辺を制限することでパフォーマンスを改善すために導入されています。

同じ目的のライブラリとしてyahoo/subscribe-ui-eventがありますが、スロットリングなどがデフォルトにあったり色々高機能でした。 なので、単純にイベントを1つにまとめるだけのazu/ui-event-observerを作ったという話でした。

他の機能的な要素はプラグインで書けるようにするのがいいんじゃないかなと思っています。