Каков наилучший способ обработки нескольких событий на одном и том же DOM node в rxjs 5.1?
fromEvent($element, 'event_name')
, но я могу указать только одно событие за раз.
Мне нужно обработать события scroll wheel touchmove touchend
.
Каков наилучший способ обработки нескольких событий на одном и том же DOM node в rxjs 5.1?
fromEvent($element, 'event_name')
, но я могу указать только одно событие за раз.
Мне нужно обработать события scroll wheel touchmove touchend
.
Примечание: это для RxJS v5. Смотрите в нижней части этого ответа для v6 эквивалент.
Вы можете использовать функцию Rx.Observable.merge
для объединения нескольких наблюдаемых потоков в один поток:
// First, create a separate observable for each event:
const scrollEvents$ = Observable.fromEvent($element, 'scroll');
const wheelEvents$ = Observable.fromEvent($element, 'wheel');
const touchMoveEvents$ = Observable.fromEvent($element, 'touchmove');
const touchEndEvents$ = Observable.fromEvent($element, 'touchend');
// Then, merge all observables into one single stream:
const allEvents$ = Observable.merge(
scrollEvents$,
wheelEvents$,
touchMoveEvents$,
touchEndEvents$
);
Если это кажется немного раздутым, мы могли бы немного очиститься, создав массив для событий, а затем сопоставить этот массив с наблюдаемыми объектами. Это работает лучше всего, если вам не нужно ссылаться на события и связанные с ними наблюдаемые отдельно в какой-то момент:
const events = [
'scroll',
'wheel',
'touchmove',
'touchend',
];
const eventStreams = events.map((ev) => Observable.fromEvent($element, ev));
const allEvents$ = Observable.merge(...eventStreams);
Теперь вы можете обрабатывать все события с помощью одной подписки:
const subscription = allEvents$.subscribe((event) => {
// do something with event...
// event may be of any type present in the events array.
});
Обновление RxJS v6
В RxJS 6 вы можете импортировать автономные функции merge
и fromEvent
эквивалентные статическим методам в v5, и использовать их таким же образом:
import { fromEvent, merge } from 'rxjs';
const scrollEvents = fromEvent($element, 'scroll');
// creating other input observables...
const allEvents$ = merge(
scrollEvents$,
wheelEvents$,
touchMoveEvents$,
touchEndEvents$
);
Вот как я предпочитаю комбинировать события:
fromEvents(dom, "scroll", "wheel", "touch", "etc...");
function fromEvents(dom, ...eventNames: string[]) {
return eventNames.reduce(
(prev, name) => Rx.merge(prev, fromEvent(dom, name)),
Rx.empty()
);
}
Вот как я бы реализовал это в новейшей версии RxJs
const events = ['scroll', 'resize', 'orientationchange']
from(events)
.pipe(
mergeMap(event => fromEvent($element, event))
)
.subscribe(
event => // Do something with the event here
)