Функция c() и базовый синтаксис

Atomico — это современная библиотека для создания веб-компонентов на JavaScript с реактивным подходом, схожим с React и Vue, но с акцентом на легковесность и совместимость с нативными веб-технологиями. Центральным элементом является функция c(), которая используется для определения компонентов. Она сочетает декларативный синтаксис с реактивным состоянием, обработкой событий и жизненным циклом компонентов.


Создание компонента с помощью c()

Функция c() принимает в качестве аргумента функцию компонента и возвращает Web Component, готовый к использованию в DOM. Типовой синтаксис выглядит так:

import { c, html } from "atomico";

const MyComponent = c(() => {
    return html`
        <div>Hello, Atomico!</div>
    `;
});
  • c() принимает функцию компонента без параметров или с объектом props.
  • html используется для декларативного создания разметки, подобно JSX, но без необходимости компиляции.
  • Возвращаемое значение c() — это класс Web Component, который можно зарегистрировать через customElements.define().

Работа с props

Props позволяют передавать данные внутрь компонента и автоматически отслеживать их изменения. Пример использования:

const Greeting = c(({ name }) => {
    return html`
        <p>Hello, ${name}!</p>
    `;
});
  • Передача атрибутов происходит через стандартный HTML:
<greeting name="Alice"></greeting>
  • Atomico автоматически преобразует строковые значения атрибутов в типы, определённые в props.

Определение типов props

Для контроля типов и значений props используется объект props на уровне компонента:

const Counter = c(
    () => {
        return html`<p>Counter component</p>`;
    },
    {
        props: {
            count: {
                type: Number,
                value: 0
            },
            label: {
                type: String,
                value: "Default"
            }
        }
    }
);
  • type задаёт ожидаемый тип значения.
  • value — значение по умолчанию.
  • Atomico отслеживает изменения props и автоматически перерендеривает компонент при их обновлении.

Реактивное состояние

Для управления внутренним состоянием используется функция useState:

import { c, html, useState } from "atomico";

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

    return html`
        <div>
            <p>Count: ${count}</p>
            <button oncl ick=${() => setCount(count + 1)}>Increment</button>
        </div>
    `;
});
  • useState возвращает массив [state, setState].
  • Любое изменение state вызывает автоматический перерендер компонента.
  • Состояние полностью реактивное и локально для компонента.

Обработка событий

События привязываются напрямую через атрибуты, используя синтаксис on[event]:

const Button = c(() => {
    const handleClick = () => console.log("Clicked!");

    return html`
        <button oncl ick=${handleClick}>Click me</button>
    `;
});
  • Все события являются стандартными DOM-событиями.
  • Поддерживаются стрелочные функции и методы, определённые внутри компонента.

Работа с жизненным циклом

Atomico предоставляет хуки жизненного цикла, аналогичные React:

  • useEffect(callback, deps) — выполняет побочные эффекты при изменении зависимостей.
  • useHost — доступ к корневому DOM-узлу компонента.
  • useRef — создание ссылок на элементы внутри шаблона.

Пример с useEffect:

import { c, html, useState, useEffect } from "atomico";

const Timer = c(() => {
    const [seconds, setSeconds] = useState(0);

    useEffect(() => {
        const interval = setInterval(() => setSeconds(s => s + 1), 1000);
        return () => clearInterval(interval);
    }, []);

    return html`<p>Seconds: ${seconds}</p>`;
});
  • Эффект срабатывает один раз при монтировании компонента, если массив зависимостей пустой.
  • Возврат функции из useEffect позволяет корректно очищать ресурсы.

Встраивание стилей

Atomico поддерживает инкапсулированные стили через шаблон css:

import { c, html, css } from "atomico";

const StyledBox = c(() => {
    return html`
        <div class="box">Styled Box</div>
    `;
}, {
    styles: css`
        .box {
            padding: 10px;
            background: #f0f0f0;
            border: 1px solid #ccc;
        }
    `
});
  • Стиль применяется только внутри компонента, не затрагивая внешние элементы.
  • Поддерживается SCSS-подобный синтаксис через обычные CSS-переменные и вложенность.

Регистрация компонента

После определения компонента его можно зарегистрировать в DOM:

customElements.define("my-component", MyComponent);
  • customElements.define() связывает имя элемента с классом компонента.
  • После регистрации компонент можно использовать в HTML как обычный тег:
<my-component></my-component>

Краткая структура компонента Atomico

  1. Импорт функций: c, html, useState, useEffect.
  2. Определение компонента через c().
  3. Использование props и реактивного состояния.
  4. Привязка событий через on[event].
  5. Опционально: стили через css.
  6. Регистрация через customElements.define().

Эта структура позволяет создавать лёгкие, реактивные и переиспользуемые веб-компоненты, полностью совместимые с нативными браузерными технологиями, при этом сохраняя декларативный и современный синтаксис JavaScript.