Делегирование

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

Основы делегирования

Делегирование событий — это техника, при которой событие, происходящее на дочернем элементе, перехватывается и обрабатывается на родительском элементе. В Atomico для этого используется система реактивных эффектов и событий, встроенная в саму библиотеку.

Ключевые принципы делегирования в Atomico:

  • Обработчик привязывается к родительскому элементу, а не к каждому дочернему.
  • События распространяются через механизм event bubbling, что позволяет родителю перехватывать действия дочерних элементов.
  • Использование селекторов или условий для фильтрации событий конкретных элементов.

Реализация делегирования

Atomico использует функцию useEvent для привязки событий к компонентам. Делегирование строится на проверке цели события через event.target и event.currentTarget.

Пример делегирования кликов внутри компонента:

import { c, useEvent } from "atomico";

function List() {
    const handleClick = (event) => {
        const item = event.target.closest("li");
        if (item) {
            console.log("Нажат элемент:", item.textContent);
        }
    };

    useEvent("click", handleClick);

    return (
        <host>
            <ul>
                <li>Элемент 1</li>
                <li>Элемент 2</li>
                <li>Элемент 3</li>
            </ul>
        </host>
    );
}

customElements.define("x-list", c(List));

В этом примере обработчик handleClick назначен на хост-компонент, а не на каждый <li>. Функция closest позволяет определить, на каком именно элементе произошло событие.

Делегирование сложных событий

Для работы с событиями, которые требуют передачи данных или сложной фильтрации, Atomico позволяет использовать кастомные события через dispatchEvent и CustomEvent.

function Button() {
    const handleClick = () => {
        dispatchEvent(new CustomEvent("button-click", {
            detail: { time: Date.now() },
            bubbles: true
        }));
    };

    return <host><button onCl ick={handleClick}>Нажми</button></host>;
}

function App() {
    const handleButtonClick = (event) => {
        console.log("Клик в компоненте Button:", event.detail.time);
    };

    useEvent("button-click", handleButtonClick);

    return <host><Button /></host>;
}

customElements.define("x-app", c(App));

Использование кастомных событий с делегированием позволяет централизованно обрабатывать действия нескольких вложенных компонентов.

Оптимизация делегирования

Atomico поддерживает реактивность через хуки useMemo и useEffect, что позволяет минимизировать повторные привязки событий и повышает производительность.

  • Выборочные обработчики — добавление условий для фильтрации только нужных элементов.
  • Отписка от событий — автоматическая при удалении компонента из DOM.
  • Использование stopPropagation — контроль всплытия событий для предотвращения нежелательной обработки.

Пример с оптимизацией:

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

function Table() {
    const handleClick = (event) => {
        const cell = event.target.closest("td");
        if (cell) console.log("Клик по ячейке:", cell.textContent);
    };

    useEffect(() => {
        document.addEventListener("click", handleClick);
        return () => document.removeEventListener("click", handleClick);
    }, []);

    return (
        <host>
            <table>
                <tr><td>1</td><td>2</td></tr>
                <tr><td>3</td><td>4</td></tr>
            </table>
        </host>
    );
}

customElements.define("x-table", c(Table));

Здесь обработчик привязан к document, что позволяет перехватывать клики вне компонента, а использование useEffect обеспечивает корректное удаление обработчика при размонтировании.

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

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

Делегирование в Atomico сочетает преимущества Web Components и реактивной модели библиотеки, позволяя создавать масштабируемые и управляемые пользовательские интерфейсы с минимальным количеством обработчиков событий.