useEvent и обработка событий

Библиотека Atomico предоставляет удобный и гибкий способ работы с компонентами Web Components через функции, напоминающие React-хуки. Одним из ключевых инструментов для взаимодействия с событиями является хук useEvent. Он позволяет подписываться на события DOM и управлять их обработкой с минимальным количеством кода.


Подключение и базовое использование useEvent

Хук useEvent импортируется напрямую из Atomico:

import { useEvent, c, html } from "atomico";

Простейший пример подписки на событие клика:

function Button() {
    const handleClick = useEvent("click", event => {
        console.log("Кнопка нажата", event);
    });

    return html`
        <button ${handleClick}>Нажми меня</button>
    `;
}

Ключевые моменты:

  • Первый аргумент useEventимя события, которое нужно слушать.
  • Второй аргумент — обработчик события, функция с параметром event.
  • Хук возвращает объект, который автоматически связывается с элементом через синтаксис ${handleClick}. Это позволяет избежать ручного добавления addEventListener и removeEventListener.

Передача опций события

useEvent поддерживает вторую сигнатуру с объектом настроек, аналогично параметрам addEventListener:

const handleClick = useEvent(
    "click",
    event => console.log("Click with capture", event),
    { capture: true, passive: true }
);

Опции, которые можно использовать:

  • capture — прослушивание события на фазе захвата.
  • passive — сообщает браузеру, что обработчик не вызывает preventDefault(), улучшает производительность скролла.
  • once — обработчик сработает один раз.

Использование событий кастомных компонентов

Atomico активно поддерживает собственные события компонентов. Например, можно подписаться на событие, эмитируемое дочерним компонентом:

function Child() {
    return html`
        <button
            oncl ick=${useEvent("custom", e => console.log("Child event", e))}
        >
            Emit Event
        </button>
    `;
}

function Parent() {
    const handleCustom = useEvent("custom", e => console.log("Parent caught", e));

    return html`
        <child-component ${handleCustom}></child-component>
    `;
}

Особенности работы с кастомными событиями:

  • События должны быть инициированы через dispatchEvent.
  • useEvent позволяет «подписываться» на события как стандартные DOM-события.
  • Для передачи данных используется CustomEvent с полем detail.

Пример эмита события из дочернего компонента:

this.dispatchEvent(new CustomEvent("custom", { detail: { value: 42 } }));

Динамическое управление обработчиками

Хук useEvent поддерживает динамическое изменение обработчиков:

const [count, setCount] = useState(0);

const handleClick = useEvent("click", event => {
    console.log("Счётчик", count);
});

return html`<button ${handleClick}>Click me</button>`;

При каждом рендере хук автоматически обновляет привязку к элементу, чтобы использовать актуальные значения из замыкания, что упрощает работу со стейтом.


Совместное использование с useRef и ссылками на элементы

useEvent может использоваться совместно с ссылками для подписки на события конкретного элемента:

const buttonRef = useRef();

useEvent(buttonRef, "click", event => {
    console.log("Clicked button via ref", event);
});

return html`<button ref=${buttonRef}>Click me</button>`;

Такой подход полезен, когда элемент создаётся динамически или требуется более точный контроль.


Обработка нескольких событий

Возможна подписка на несколько событий через массив:

const handleEvents = useEvent(["mouseenter", "mouseleave"], event => {
    console.log("Событие мыши:", event.type);
});
  • Хук автоматически создаёт обработчики для каждого события.
  • Обеспечивается корректное удаление обработчиков при размонтировании компонента.

Рекомендации по производительности

  • Использовать опцию passive: true для событий скролла и тач-событий.
  • Избегать создания анонимных функций в рендере, если обработчик не зависит от текущего состояния.
  • Для сложных компонентов можно комбинировать useEvent с useCallback для оптимизации повторного рендера.

Взаимодействие с глобальными событиями

useEvent поддерживает подписку на события window и document:

const handleResize = useEvent(window, "resize", event => {
    console.log("Размер окна изменён", window.innerWidth);
});
  • Хук автоматически управляет подпиской и удалением слушателя при размонтировании.
  • Позволяет организовать глобальные реакции на изменение состояния браузера без ручного контроля жизненного цикла.

Особенности удаления обработчиков

useEvent гарантирует корректное удаление обработчиков при размонтировании элемента или компонента. Это исключает утечки памяти и обеспечивает стабильность приложения.

  • При использовании с рефами удаление происходит автоматически.
  • Для динамически создаваемых элементов достаточно оставить привязку через ${handleEvent} или реф.

useEvent в Atomico представляет собой мощный инструмент для работы с событиями, обеспечивающий безопасное, удобное и декларативное подключение обработчиков, как для стандартных DOM-событий, так и для кастомных событий компонентов. Его гибкость позволяет создавать интерактивные компоненты без избыточного кода и ошибок управления жизненным циклом событий.