Прямой доступ к элементам

Atomico — современная библиотека для создания веб-компонентов на JavaScript, основанная на реактивном подходе. Одной из важных особенностей является возможность прямого взаимодействия с DOM-элементами через рефы, что обеспечивает гибкость при работе с внешними библиотеками, анимациями или сложной логикой интерфейса.


Использование ref для доступа к элементам

В Atomico доступ к элементам осуществляется через рефы. Реф представляет собой объект с единственным свойством current, которое указывает на соответствующий DOM-элемент.

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

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

function MyComponent() {
    const inputRef = useRef();

    useEffect(() => {
        if (inputRef.current) {
            inputRef.current.focus();
        }
    }, []);

    return (
        <host>
            <input ref={inputRef} type="text" placeholder="Введите текст" />
        </host>
    );
}

customElements.define("my-component", c(MyComponent));

В этом примере:

  • useRef() создаёт объект рефа.
  • ref={inputRef} связывает DOM-элемент с объектом.
  • useEffect гарантирует, что доступ к элементу выполняется после монтирования компонента.

Динамическая работа с несколькими элементами

Для списка элементов часто используют массив рефов. Atomico позволяет динамически создавать и привязывать рефы:

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

function ListComponent({ items }) {
    const refs = useRef([]);

    useEffect(() => {
        refs.current.forEach(el => {
            if (el) el.style.backgroundColor = "lightyellow";
        });
    }, [items]);

    return (
        <host>
            {items.map((item, index) => (
                <div ref={el => refs.current[index] = el} key={index}>
                    {item}
                </div>
            ))}
        </host>
    );
}

customElements.define("list-component", c(ListComponent));

Здесь создаётся массив refs.current, где каждый элемент ссылается на соответствующий DOM-узел. Это удобно для применения стилей, анимаций или вызова методов DOM-элементов.


Доступ к дочерним компонентам

Atomico позволяет получать доступ к внутренним элементам других компонентов, используя рефы и методы стандартного DOM. Например, для вызова метода дочернего веб-компонента:

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

function ParentComponent() {
    const childRef = useRef();

    const callChildMethod = () => {
        childRef.current?.doSomething();
    };

    return (
        <host>
            <button oncl ick={callChildMethod}>Вызвать метод дочернего компонента</button>
            <child-component ref={childRef}></child-component>
        </host>
    );
}

function ChildComponent() {
    const doSomething = () => {
        console.log("Метод вызван!");
    };

    return <host></host>;
}

customElements.define("parent-component", c(ParentComponent));
customElements.define("child-component", c(ChildComponent));

Использование рефов даёт возможность контролировать дочерние компоненты без обхода стандартного DOM через querySelector.


Особенности жизненного цикла и работы с рефами

  • Монтирование: ref.current становится доступным после первого рендера.
  • Размонтирование: при удалении элемента ref.current обнуляется, что позволяет безопасно очищать ресурсы.
  • Реактивность: изменение рефа не вызывает повторный рендер. Для реактивных данных используются useState и useEffect.

Примеры применения прямого доступа

  1. Фокус на элементе при монтировании: Удобно для форм и модальных окон.

  2. Измерение размеров элементов: Получение ширины и высоты через ref.current.getBoundingClientRect().

  3. Анимации и интеграция с библиотеками: Прямой доступ необходим для работы с GreenSock, Anime.js или сторонними плагинами.

  4. Манипуляции с DOM в сложных компонентах: Например, перемещение элементов, создание кастомных событий или управление scroll-положением.


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

  • Не хранить в рефах реактивные данные. Для этого служат useState или useMemo.
  • Всегда проверять наличие элемента через условие if (ref.current).
  • При работе с массивами рефов использовать индекс или уникальный идентификатор для корректного сопоставления.
  • Использовать рефы для интеграции с внешними библиотеками, а не для обычного рендеринга UI.

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