Инициализация компонента

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

import { c, html } from "atomico";

function MyComponent() {
    return html`
        
Привет, Atomico!
`; } customElements.define("my-component", c(MyComponent));

Функция c

Функция c — ядро процесса инициализации. Она принимает компонент и возвращает класс, совместимый с Custom Elements, что позволяет использовать компонент как обычный HTML-тег:

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

Особенности c:

  • Автоматическое связывание реактивных свойств и атрибутов.
  • Поддержка хуков useState, useEffect и других реактивных механизмов Atomico.
  • Позволяет компоненту интегрироваться в DOM без дополнительного обвязочного кода.

Определение и регистрация компонента

Компонент должен быть зарегистрирован через customElements.define. Первый аргумент — это имя нового тега, второй — класс, возвращаемый функцией c.

customElements.define("user-card", c(UserCard));

После этого компонент можно использовать в HTML:

Свойства компонента

Atomico поддерживает реактивные свойства. Они определяются через статическое свойство props функции компонента:

function UserCard({ name, age }) {
    return html`
        

Имя: ${name}

Возраст: ${age}

`; } UserCard.props = { name: String, age: Number }; customElements.define("user-card", c(UserCard));

Ключевые моменты работы с props:

  • Привязка свойств к атрибутам HTML происходит автоматически.
  • Изменение свойства компонента вызывает повторный рендер.
  • Типизация свойств помогает избежать ошибок при передаче данных.

Рендеринг и реактивность

Atomico использует реактивную модель, основанную на хуках. После инициализации компонент автоматически реагирует на изменения props и состояния:

import { useState } from "atomico";

function Counter() {
    const [count, setCount] = useState(0);

    return html`
        

Счетчик: ${count}

`; } customElements.define("counter-element", c(Counter));

Особенности реактивности:

  • useState возвращает массив [значение, функция изменения].
  • Любое изменение состояния инициирует повторный рендер только компонента, где произошло изменение.
  • Вложенные компоненты также обновляются автоматически при изменении переданных props.

Подключение стилей

Atomico позволяет использовать CSS внутри компонента через шаблон html:

function StyledBox() {
    return html`
        
        
Стилизация встроена
`; } customElements.define("styled-box", c(StyledBox));

Преимущества встроенных стилей:

  • Инкапсуляция — стили применяются только к данному компоненту.
  • Полная совместимость с Shadow DOM, что предотвращает конфликты с глобальными стилями.
  • Возможность динамически менять стили через реактивные переменные.

Работа с событиями

События обрабатываются как обычные атрибуты DOM-элементов. Atomico автоматически связывает их с функциями:

function ClickableButton() {
    const handleClick = () => alert("Нажато!");

    return html`
        
    `;
}

customElements.define("clickable-button", c(ClickableButton));

Особенности событий:

  • События внутри компонента не требуют addEventListener.
  • Использование стрелочных функций сохраняет контекст компонента.
  • Можно комбинировать с useState для реактивного обновления интерфейса.

Использование слотов

Atomico поддерживает стандартные слоты Shadow DOM, что позволяет компоновать компоненты:

function Card() {
    return html`
        
`; } customElements.define("custom-card", c(Card));

В HTML это выглядит так:


    

Контент внутри слота

Слоты позволяют создавать гибкие компоненты, где структура определяется потребителем, а логика и стили остаются инкапсулированными.

Инициализация с параметрами по умолчанию

Свойства можно задавать с начальными значениями, что особенно полезно для повторно используемых компонентов:

function Badge({ label = "Новый", color = "blue" }) {
    return html`${label}`;
}

Badge.props = {
    label: String,
    color: String
};

customElements.define("badge-element", c(Badge));

Это упрощает интеграцию и снижает количество boilerplate-кода при использовании компонентов.