В библиотеке Atomico каждый компонент представляет собой функцию, возвращающую виртуальный DOM, который библиотека трансформирует в реальные DOM-узлы. Работа с узлами строится вокруг концепций рендеринга, состояния и реактивных эффектов, что позволяет управлять структурой и поведением элементов без прямой манипуляции с DOM через стандартные методы JavaScript.
Для создания элементов используется функция
h(tag, props, ...children), где:
tag — строка с именем HTML-тега или компонент
Atomico;props — объект с атрибутами и событиями;children — дочерние узлы, строки или массивы
узлов.Пример создания узла с вложенными элементами:
import { h, render } from "atomico";
function MyComponent() {
return h("div", { class: "container" },
h("h1", {}, "Заголовок"),
h("p", {}, "Описание компонента")
);
}
render(h(MyComponent), document.body);
Ключевой момент: Atomico автоматически отслеживает изменения состояния и обновляет только те части DOM, которые изменились, минимизируя лишние операции.
Atomico предоставляет способ получения ссылки на конкретный DOM-узел через рефы. Это удобно для прямых манипуляций, например, фокусировки или измерений:
import { useRef, h } from "atomico";
function InputFocus() {
const inputRef = useRef();
function focusInput() {
inputRef.current.focus();
}
return h("div", {},
h("input", { ref: inputRef }),
h("button", { onclick: focusInput }, "Фокус")
);
}
Особенности:
useRef создаёт объект с полем current,
который после монтирования компонента указывает на DOM-узел.ref.current не вызывает повторного рендеринга
компонента.Состояние компонентов в Atomico управляется с помощью хука
useState. Изменение состояния инициирует повторный
рендер только тех узлов, которые зависят от этого
состояния:
import { useState, h } from "atomico";
function Counter() {
const [count, setCount] = useState(0);
return h("div", {},
h("span", {}, `Счетчик: ${count}`),
h("button", { onclick: () => setCount(count + 1) }, "Увеличить")
);
}
Вывод: любые изменения count не требуют
ручной работы с DOM — Atomico обновляет текст внутри span
автоматически.
Атрибуты и классы задаются через объект props. Для
динамических значений удобно использовать шаблонные
строки или вычисляемые свойства:
function ToggleButton({ active }) {
return h("button", {
class: active ? "btn active" : "btn",
onclick: () => console.log("Кнопка нажата")
}, active ? "Включено" : "Выключено");
}
class и другие атрибуты обновляются при изменении
состояния без полного перерендера родителя.onclick,
oninput, onchange) и позволяет назначать
несколько обработчиков через массивы.Для динамического отображения узлов применяются стандартные
конструкции JavaScript. Atomico корректно рендерит массивы и пропускает
null или undefined:
function ItemList({ items }) {
return h("ul", {},
items.map(item => h("li", {}, item)),
items.length === 0 && h("li", {}, "Список пуст")
);
}
Особенности:
key) в списках помогают библиотеке
оптимизировать повторный рендер при изменении массива.null позволяет легко управлять
условным отображением.Atomico поддерживает ряд специальных атрибутов, влияющих на работу с узлами:
ref — ссылка на узел, как уже показано выше.key — уникальный идентификатор для элементов в
списках.slot — позволяет размещать дочерние узлы в компонентах
с именованными слотами.Пример использования слотов:
function Card({ children }) {
return h("div", { class: "card" },
h("header", {}, h("slot", { name: "header" })),
h("main", {}, h("slot", {}))
);
}
render(
h(Card, {}, [
h("h2", { slot: "header" }, "Заголовок карточки"),
h("p", {}, "Содержимое карточки")
]),
document.body
);
Хук useEffect позволяет выполнять операции после
монтирования или обновления узлов:
import { useEffect, h } from "atomico";
function AutoFocusInput() {
const inputRef = useRef();
useEffect(() => {
inputRef.current.focus();
}, []); // Пустой массив — эффект выполняется один раз при монтировании
return h("input", { ref: inputRef });
}
useEffect предотвращает необходимость в
DOMContentLoaded и ручной проверке готовности узла.Atomico упрощает привязку событий. Поддерживаются как стандартные события DOM, так и пользовательские:
function InputLogger() {
const [value, setValue] = useState("");
return h("input", {
value,
oninput: (e) => setValue(e.target.value)
});
}
Event) в обработчик.h и обновляются реактивно при
изменении состояния.useRef обеспечивает доступ к реальным
DOM-элементам.key.useEffect) позволяют безопасно выполнять
операции после рендеринга.Манипуляция узлами в Atomico строится вокруг чистой декларативной модели, где основной задачей становится управление состоянием и структурой, а не непосредственное вмешательство в DOM, что обеспечивает эффективность и предсказуемость интерфейсов.