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