RxJSのストリームの扱いに慣れるためにいろいろ試してみたメモ。
サンプルコードではインポートの記述を省略しているので、実際の動きはstackblitzで確認するといいかもです。
基本編
fromEvent
を使って、プリミティブなクリックイベントを取得してみます。
次のようなHTMLを用意します。
<button id="button">押してね</button>
fromEvent
の第一引数に対象のHTMLElementを第二引数にイベント名を入力します。
const button: HTMLElement = document.getElementById('button');
// click
const click$: Observable<Event> = fromEvent(button, 'click');
// mousedown
const mousedown$: Observable<Event> = fromEvent(button, 'mousedown');
// mouseup
const mouseup$: Observable<Event> = fromEvent(button, 'mouseup');
それぞれのイベントストリームは、pipe()
してゴニョゴニョするなりsubscribe
するなり好きに扱う事ができるようになります。
ダブルクリック
まず、基本編同様にfromEvent
でdblclick
イベントをハンドリングする方法があります。
const button: HTMLElement = document.getElementById('button');
// dblclick
const dblclick$: Observable<Event> = fromEvent(button, 'dblclick');
別の方法として、次のようにハンドリングする用法も考えられます。
(ダブルクリックの間隔をアプリケーション側で調整したい場合など?)
const button: HTMLElement = document.getElementById('button');
const click$: Observable<Event> = fromEvent(button, 'click');
const dblclick$ = click$.pipe(
bufferTime(1000),
map((event: Event[]) => event.length),
filter((eventLength: number) => eventLength === 2),
);
bufferTime
で一定期間のイベントストリームをまとめて流し、そのイベント数をフィルターして条件にあったクリックイベントのみを取得しています。
n秒間にx回クリック
これは、ダブルクリックの2つめとほぼ同じですが、次のように実現できますね。
const button: HTMLElement = document.getElementById('button');
const click$: Observable<Event> = fromEvent(button, 'click');
// 5 times in 2 seconds
const dblclick$ = click$.pipe(
bufferTime(2000),
map((event: Event[]) => event.length),
filter((eventLength: number) => eventLength === 5),
);
長押し
const button: HTMLElement = document.getElementById('button');
const mouseDown$: Observable<MouseEvent> = fromEvent(button, 'mousedown');
const mouseUp$: Observable<MouseEvent> = fromEvent(button, 'mouseup');
// long press 2 seconds
const longpress$ = mouseDown$.pipe(
mergeMap((e) => {
return of(e).pipe(
delay(2000),
takeUntil(mouseUp$),
);
}),
);
ポイントは、subscribeをキャンセルする条件(takeUntil)をmergeMap
で返す内側のObservableに対して設定することです。
これを、外側(全体)のObservableに対して設定してしまうと、このイベントが一回発火した以降、再度発火しなくなってしまいます。
終わりに
RxJS楽しいです(小並感)。
これ何に使うの感は若干ありますが、上記で紹介したストリームをいい感じに組み合わせて複雑なパターンを作り、「隠しページへのリンクを配置する」などといった使い方ができるのではないでしょうか。