@webeach/event-manager
Version:
EventManager is a library for simplifying event handling in JavaScript
352 lines (244 loc) • 13.6 kB
Markdown
# `EventManager`
**EventManager** — это пакет для упрощенной работы с событиями в JavaScript. С помощью этого пакета вы сможете легко управлять подписками на события, отключать их и обрабатывать их более удобным способом.
Основные задачи, которые решает данный пакет:
+ Компактное и понятное управление обработчиками событий.
+ Работа с множеством разных событий одновременно.
+ Типизация собственных объектов событий.
## 📦 Установка
```bash
npm install @webeach/event-manager
```
или
```bash
yarn add @webeach/event-manager
```
## 🚀 Быстрый старт
### Подписка на глобальные события в `window`
```js
import { listen } from '@webeach/event-manager';
listen(window)
.add('resize', () => console.log('Размер окна был изменён!'))
.add('scroll', () => console.log('Окно было прокручено!'));
```
### Подписка на события `DOM` элемента.
```js
import { listen } from '@webeach/event-manager';
const myButton = document.getElementById('my-button');
listen(myButton)
.add('click', () => console.log('Произошёл клик на кнопке!'))
.add('focus', () => console.log('Произошёл фокус на кнопке!'));
```
### Подписка и удаление событий
```js
import { listen } from '@webeach/event-manager';
const myButton = document.getElementById('my-button');
const myButtonListener = listen(myButton)
.add('click', () => console.log('Произошёл клик на кнопке!'));
// Отписываемся от события через 10 секунд
window.setTimeout(() => {
myButtonListener.remove('click');
}, 10000);
```
### Собственный объект управления событиями
```js
import { listen } from '@webeach/event-manager';
const myListener = listen();
myListener
.add('test', () => console.log('Было вызвано событие "test"'))
.add('hello', (event) => console.log(`Привет, ${event.detail.name}!`));
// Вызываем события через 3 секунды
window.setTimeout(() => {
myListener.trigger('test');
myListener.trigger('hello', {
name: 'Александр',
});
}, 3000);
```
### Отписка от всех событий
```js
import { listen } from '@webeach/event-manager';
const windowListener = listen(window);
windowListener
.add('focus', () => console.log('Было вызвано событие "focus"'))
.add('resize', () => console.log('Было вызвано событие "resize"'))
.add('scroll', () => console.log('Было вызвано событие "scroll"'));
// Отписываемся от событий через 10 секунд
window.setTimeout(() => {
windowListener.remove();
// либо: windowListener.remove(['focus', 'resize', 'scroll']);
}, 3000);
```
### Множественные события
```js
import { listen } from '@webeach/event-manager';
const myButton = document.getElementById('my-button');
const myButtonListener = listen(myButton);
// Оба обработчика сработают
myButtonListener.add('click', () => console.log('Произошёл клик на кнопке!'));
myButtonListener.add('click', () => console.log('Произошёл клик на кнопке!'));
// Оба обработчика сработают
myButtonListener.add('focus', [
() => console.log('Произошёл фокус на кнопке!'),
() => console.log('Произошёл фокус на кнопке!'),
]);
```
## 🛠 API
Объект `EventManager` предоставляет следующие методы для работы с обработчиками событий:
### `add(type, handler | handler[], options?)`
Добавляет новый обработчик события в прослушиватель.
| Параметр | Тип | Описание | Пример |
|-----------|---------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|---------------------|
| `type` | `string` | тип события | `"click"`, `"focus` |
| `handler` | `function`, `array` | функция или массив функций, которые будут вызваны при отработке события. Функция также принимает аргумент `event`, который содержит данные о событии. | `(event) => {}` |
| `options` | `object` | объект дополнительных настроек, который может содержать следующие необязательные `boolean` свойства: `capture` (событие будет перехвачено, актуально для `DOM` событий), `once` (событие будет отработано только один раз). | |
### `capture(type, handler | handler[])`
Удобная альтернатива `add(type, handler, { capture: true })`.
### `once(type, handler | handler[])`
Удобная альтернатива `add(type, handler, { once: true })`.
### `remove(type | type[])`
Удаляет обработчики событий из прослушиватель.
| Параметр | Тип | Описание | Пример |
|-----------|----------------------|--------------------------------------------------------------------------------|---------------------------------|
| `type` | `string`, `string[]` | тип события или массив типов событий, которые будут удалены из прослушивателя. | `"click"`, `["click", "focus"]` |
❗️ Обратите внимание:
+ Будут удалены только те события, которые были назначены через прослушиватель. События, которые были назначены через `addEventListener` будут проигнорированы.
### `remove()`
Удаляет все обработчики событий из прослушивателя.
❗️ Обратите внимание:
+ Чтобы удалить все обработчики событий из прослушивателя – нужно вызвать `remove` без параметров.
+ Будут удалены только те события, которые были назначены через прослушиватель. События, которые были назначены через `addEventListener` будут проигнорированы.
### `trigger(type, detail?)`
Вызывает указанное событие.
| Параметр | Тип | Описание | Пример |
|----------|----------|---------------------------------------------------------------------------------|-------------------------|
| `type` | `string` | тип события, которое будет вызвано. | `"click"` |
| `detail` | `object` | необязательный объект, который будет передан в объект события (`event.detail`). | `{ name: 'Анастасия' }` |
### `trigger(event)`
Вызывает указанное событие.
| Параметр | Тип | Описание | Пример |
|----------|----------|---------------------------------------------------------------------------------|--------------------------|
| `event` | `Event` | объект события наследуемое от объекта `Event`. | `new MouseEvent('click')` |
## 🧩 Типизация
Этот пакет полностью совместим с `typescript` и автоматически определяет тип события, которые зависят от наблюдаемого объекта.
Вы можете типизировать собственный интерфейс пользовательских событий (см. пример ниже).
```ts
import { listen } from '@webeach/event-manager';
interface MyCustomGlobalHandlers {
one: CustomEvent,
hello: CustomEvent<{ name: string }>,
}
const windowListener = listen<Window, MyCustomGlobalHandlers>(window);
windowListener.add('one', (event) => {
console.log('Было вызвано событие "one"');
});
windowListener.add('hello', (event) => {
console.log(`Привет, ${event.detail.name}!`);
});
windowListener.trigger('one');
windowListener.trigger('hello', {
name: 'Анастасия',
});
```
## 📖 Реальные примеры
### Изменение текста по `hover`
В этом примере мы изменяем текст кнопки при наведении.
```ts
import { listen } from '@webeach/event-manager';
const basketButton = document.querySelector('.basket-button') as HTMLButtonElement;
listen(basketButton, {
mouseenter: () => {
basketButton.textContent = 'Перейти в корзину';
},
mouseleave: () => {
basketButton.textContent = 'Корзина покупок';
},
})
```
### Отслеживание клика по ссылкам
В этом примере мы отслеживаем все клики по ссылкам документа, чтобы отправлять статистику.
```ts
import { listen } from '@webeach/event-manager';
listen(document)
.add('click', ({ target }) => {
const nearestAnchor = target.closest('a') as HTMLAnchorElement | null;
if (
nearestAnchor !== null &&
nearestAnchor.href !== '' && (
nearestAnchor.hostname !== window.location.hostname ||
nearestAnchor.pathname !== window.location.pathname ||
nearestAnchor.search !== window.location.search)
) {
window.navigator.sendBeacon(ENV.CLICK_TRACKER_URL, {
type: 'linkClick',
data: {
link: nearestAnchor.href,
},
});
}
});
```
### Работа с `postmessage`
В этом примере, `window` прослушивает событие `message`, чтобы актуализировать высоту `iframe`.
```ts
import { listen } from '@webeach/event-manager';
const banner = document.getElementById('banner') as HTMLIFrameElement;
const windowListener = listen(window);
windowListener.add('message', (event) => {
const { type, height } = event.data || {};
if (type === 'setHeight' && typeof height === 'number') {
banner.style.height = `${height}px`;
}
});
```
### Отслеживание прокрутки документа в `react`
В этом примере, мы имеем `React` компонент, которые отслеживает прокрутку документ и в зависимости от значения — отображает кнопку прокрутки "наверх".
```tsx
import { FC, PropsWithChildren, useEffect, useState } from 'react';
import { listen } from '@webeach/event-manager';
const SHOW_TOP_BUTTON_SCROLL_OFFSET = 120;
export const PageLayout: FC<PropsWithChildren> = () => {
const { children } = props;
const [topButtonShown, setTopButtonShown] = useState(false);
const handleTopButtonClick = () => {
window.scrollTo(0, 0);
};
useEffect(() => {
const { remove } = listen(window, {
scroll: () => {
setTopButtonShown(
window.scrollY >= SHOW_TOP_BUTTON_SCROLL_OFFSET,
);
},
});
return () => {
remove();
};
}, [topButtonShown]);
return (
<div className="page-layout">
<main className="page-layout__content">
{children}
</main>
{topButtonShown && (
<button
aria-label="Прокрутить вверх"
className="page-layout__top-button"
onClick={handleTopButtonClick}
/>
)}
</div>
);
};
```
## 📄 Лицензия
Этот проект распространяется под лицензией MIT.
## 🌐 Языки
+ [🇺🇸 English](./README.md)
+ [🇷🇺 Русский](./README.ru.md)