Работа с обработчиками событий

Haunted — это лёгкая библиотека для создания веб-компонентов с использованием функционального подхода, построенного на хуках. Важным аспектом интерактивных компонентов является работа с обработчиками событий, которые позволяют реагировать на действия пользователя и изменять состояние приложения.


Назначение и синтаксис обработчиков

В Haunted обработчики событий привязываются напрямую к элементам через атрибуты в шаблоне, аналогично JSX в React. Основной синтаксис:

html`<button @click=${handleClick}>Нажми меня</button>`
  • @click — событие DOM, к которому привязывается функция.
  • ${handleClick} — ссылка на функцию, которая будет вызвана при срабатывании события.

Haunted использует лит-html для рендеринга, поэтому поддерживается динамическая привязка функций без дополнительного обёртывания. Внутри функции обработчика доступен объект события, как в обычном Jav * aScript:

function handleClick(event) {
  console.log(event.target);
}

Работа с состоянием внутри обработчиков

Haunted предоставляет хук useState для управления локальным состоянием. Состояние часто изменяется внутри обработчиков событий:

import { html, component } from 'haunted';
import { useState } from 'haunted';

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

  const increment = () => setCount(count + 1);

  return html`
    <div>
      <p>Счёт: ${count}</p>
      <button @click=${increment}>Увеличить</button>
    </div>
  `;
}

customElements.define('my-counter', component(Counter));

Особенности:

  • useState создаёт реактивное состояние.
  • Любое обновление через setCount вызывает повторный рендер компонента.
  • Обработчик может использовать текущее значение состояния и вычислять новое.

Передача аргументов в обработчики

Иногда нужно передать дополнительные параметры в обработчик, помимо объекта события. В Haunted это делается с помощью стрелочной функции:

function handleItemClick(id, event) {
  console.log('Клик по элементу', id);
}

const items = [1, 2, 3];

html`
  <ul>
    ${items.map(
      item => html`<li @click=${(e) => handleItemClick(item, e)}>Элемент ${item}</li>`
    )}
  </ul>
`

Важно: нельзя писать @click=${handleItemClick(item)} — это вызовет функцию немедленно при рендере, а не при событии.


Отписка от событий и управление жизненным циклом

Haunted поддерживает хуки useEffect для управления побочными эффектами, включая добавление и удаление обработчиков событий на сторонние элементы:

import { useEffect } from 'haunted';

function ClickLogger() {
  useEffect(() => {
    const onDocumentCl ick = (e) => console.log('Документ кликнут', e);
    document.addEventListener('click', onDocumentClick);
    return () => document.removeEventListener('click', onDocumentClick);
  }, []);

  return html`<p>Нажимайте в любом месте страницы</p>`;
}

customElements.define('click-logger', component(ClickLogger));

Пояснения:

  • Возвращаемая функция из useEffect выполняется при размонтировании компонента или перед следующим вызовом эффекта.
  • Это предотвращает утечки памяти и накопление обработчиков.

Особенности работы с this в обработчиках

В Haunted функции-компоненты не имеют собственного this. Использование this внутри обработчиков в шаблонах может привести к ошибкам. Вместо этого следует использовать переменные, полученные через хуки:

function Timer() {
  const [seconds, setSeconds] = useState(0);

  const tick = () => setSeconds(seconds + 1);

  useEffect(() => {
    const interval = setInterval(tick, 1000);
    return () => clearInterval(interval);
  }, [seconds]);

  return html`<p>Прошло секунд: ${seconds}</p>`;
}

customElements.define('my-timer', component(Timer));

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

Haunted позволяет работать с кастомными событиями через стандартный DOM API. Для их генерации используется CustomEvent:

const event = new CustomEvent('my-event', {
  detail: { message: 'Привет!' },
  bubbles: true,
  composed: true
});
element.dispatchEvent(event);

В родительском компоненте можно слушать такое событие так же, как стандартное:

html`<my-child @my-event=${handleMyEvent}></my-child>`

Важные рекомендации

  • Сохранять функции обработчиков в переменных или константах, чтобы избежать лишних пересозданий при каждом рендере.
  • Использовать стрелочные функции для передачи аргументов, но избегать прямого вызова при рендере.
  • Всегда очищать побочные эффекты через useEffect при работе с глобальными событиями.
  • Не использовать this внутри функций-компонентов Haunted, полагаясь на хуки и замыкания.

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