В Haunted обработка событий в шаблонах построена на привязке функций
непосредственно к атрибутам HTML-элементов через синтаксис
@event. Это позволяет компоненту реагировать на действия
пользователя, такие как клики, ввод текста или наведение мыши, без
необходимости вручную подписываться на события через
addEventListener.
import { html, component } from 'haunted';
function Counter() {
let count = 0;
function increment() {
count++;
this.requestUpdate();
}
return html`
<div>
<p>Счётчик: ${count}</p>
<button @click=${increment}>Увеличить</button>
</div>
`;
}
customElements.define('my-counter', component(Counter));
В этом примере ключевой момент — использование
@click=${increment}. Haunted автоматически привязывает
функцию к событию click на кнопке.
Функция обработчика получает контекст элемента, к которому она
привязана, через this. Если функция объявлена как метод
компонента, this ссылается на текущий экземпляр компонента.
Для стрелочных функций this наследуется из внешней области
видимости, что иногда удобно для работы с локальными переменными.
function Counter() {
let count = 0;
const increment = () => {
count++;
this.requestUpdate(); // здесь this не будет ссылаться на компонент
}
// правильнее использовать обычную функцию
function incrementProper() {
count++;
this.requestUpdate();
}
return html`
<button @click=${incrementProper}>Увеличить</button>
`;
}
Нередко требуется передавать параметры в обработчики. В Haunted это делается через обёртку-функцию:
function Counter() {
let count = 0;
function add(value) {
count += value;
this.requestUpdate();
}
return html`
<button @click=${() => add.call(this, 5)}>Добавить 5</button>
`;
}
Использование .call(this, ...) гарантирует, что контекст
обработчика будет правильным, даже если функция вызывается внутри
стрелочной обёртки.
Haunted поддерживает генерацию списков с привязкой событий к каждому элементу:
function ItemList({ items }) {
function remove(index) {
items.splice(index, 1);
this.requestUpdate();
}
return html`
<ul>
${items.map((item, i) => html`
<li>
${item} <button @click=${() => remove.call(this, i)}>Удалить</button>
</li>
`)}
</ul>
`;
}
Каждая кнопка получает индивидуальный обработчик через стрелочную функцию, обеспечивая доступ к правильному индексу.
EventОбработчики получают объект события по умолчанию, что позволяет
работать с его свойствами: event.target,
event.preventDefault(),
event.stopPropagation().
function FormComponent() {
function handleSubmit(event) {
event.preventDefault();
console.log('Форма отправлена');
}
return html`
<form @submit=${handleSubmit}>
<input type="text" name="name" />
<button type="submit">Отправить</button>
</form>
`;
}
Haunted позволяет задавать разные события для одного элемента, просто
добавляя несколько атрибутов @event:
function HoverButton() {
function onEnter() { console.log('Мышь над кнопкой'); }
function onLeave() { console.log('Мышь покинула кнопку'); }
return html`
<button @mouseenter=${onEnter} @mouseleave=${onLeave}>Наведи меня</button>
`;
}
Помимо стандартных DOM-событий, компоненты Haunted могут обрабатывать кастомные события:
function ChildComponent() {
function notify() {
this.dispatchEvent(new CustomEvent('child-action', { detail: 'данные', bubbles: true }));
}
return html`<button @click=${notify}>Сообщить родителю</button>`;
}
function ParentComponent() {
function handleChildAction(event) {
console.log('Получено событие от ребёнка:', event.detail);
}
return html`<child-component @child-action=${handleChildAction}></child-component>`;
}
Использование bubbles: true позволяет родительскому
компоненту ловить событие, исходящее от дочернего.
requestUpdate не требуется.@event=${handler} — декларативная привязка
событий..call(this).Event для предотвращения стандартного
поведения или получения данных.Эти механизмы обеспечивают гибкую, безопасную и декларативную обработку событий в компонентах Haunted, сохраняя реактивность и удобство построения интерфейсов.