Определение свойств через props

Atomico — это современная библиотека для построения веб-компонентов с использованием привычного синтаксиса JavaScript и JSX. Одной из ключевых особенностей является строгая типизация и декларативное определение свойств компонента через props. Это позволяет не только передавать данные внутрь компонента, но и задавать их типы, значения по умолчанию и реактивность.


Объявление props

В Atomico props объявляются с помощью функции props, которая возвращает объект с описанием свойств. Каждое свойство может содержать следующие параметры:

  • type — конструктор типа значения (String, Number, Boolean, Array, Object, Function).
  • value — значение по умолчанию.
  • reflect — булевое значение, указывающее, должно ли свойство отражаться на атрибуте элемента.
  • observer — функция, которая вызывается при изменении значения свойства.

Пример объявления props:

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

function Counter({ count }) {
    return <div>Count: {count}</div>;
}

Counter.props = props({
    count: {
        type: Number,
        value: 0,
        reflect: true,
        observer: (newValue, oldValue) => {
            console.log(`Count изменился с ${oldValue} на ${newValue}`);
        }
    }
});

export const counter = c(Counter);

В этом примере свойство count имеет тип Number, значение по умолчанию 0, отражается на HTML-атрибут и отслеживает изменения через observer.


Реактивность props

Atomico автоматически делает props реактивными. Любое изменение значения свойства внутри компонента вызывает повторный рендер. При этом можно комбинировать props с локальным состоянием через useState для более сложной логики.

function Timer({ initial }) {
    const [time, setTime] = useState(initial);

    setInterval(() => setTime(time + 1), 1000);

    return <div>Time: {time}</div>;
}

Timer.props = props({
    initial: Number
});

export const timer = c(Timer);

Здесь initial передается как prop, а time — локальное состояние, синхронизированное с пропом только при инициализации.


Типы props и их использование

  • String — текстовые значения.
  • Number — числа, включая отрицательные и дробные.
  • Boolean — булевы значения; при передаче атрибута HTML достаточно указать его присутствие (<my-component disabled>).
  • Array / Object — сложные структуры данных; рекомендуется передавать через JavaScript-синтаксис, а не через атрибуты HTML.
  • Function — обработчики событий или колбэки.
function Button({ label, onClick }) {
    return <button oncl ick={onClick}>{label}</button>;
}

Button.props = props({
    label: String,
    onClick: Function
});

Отражение props на атрибуты (reflect)

Свойство reflect: true позволяет синхронизировать значение prop с HTML-атрибутом. Это особенно полезно для интеграции с CSS или сторонними библиотеками, которые читают атрибуты DOM.

function Toggle({ active }) {
    return <div className={active ? "on" : "off"}>Toggle</div>;
}

Toggle.props = props({
    active: {
        type: Boolean,
        value: false,
        reflect: true
    }
});

При изменении active атрибут active элемента также обновляется в DOM.


Observer для отслеживания изменений

Observer-функция вызывается при любом изменении prop, что позволяет реализовать дополнительные побочные эффекты:

function ProgressBar({ progress }) {
    return <div style={{ width: `${progress}%`, background: "blue", height: "20px" }}></div>;
}

ProgressBar.props = props({
    progress: {
        type: Number,
        value: 0,
        observer: (newVal, oldVal) => {
            console.log(`Прогресс изменился с ${oldVal}% на ${newVal}%`);
        }
    }
});

Observer получает два аргумента: новое и предыдущее значение свойства.


Применение пропсов по умолчанию

Значения по умолчанию задаются через поле value и используются, если компонент был создан без передачи конкретного значения:

function Greeting({ name }) {
    return <h1>Hello, {name}!</h1>;
}

Greeting.props = props({
    name: { type: String, value: "Guest" }
});

Если <greeting></greeting> будет добавлен в DOM без атрибута name, текст по умолчанию будет "Guest".


Работа с динамическими props

Props можно менять динамически через Jav * aScript:

const app = document.querySelector("my-counter");
app.count = 10; // автоматически вызовет рендер с новым значением

При этом срабатывает observer, а также обновляется DOM, если свойство отражается на атрибуте.


Комбинация props и слотов

Atomico позволяет комбинировать props с slots для передачи сложного контента внутрь компонента. Props при этом отвечают за логику, а слоты — за визуальное представление:

function Card({ title }) {
    return (
        <div class="card">
            <h2>{title}</h2>
            <slot></slot>
        </div>
    );
}

Card.props = props({
    title: { type: String }
});

Сравнение с обычными веб-компонентами

Использование props в Atomico заменяет традиционное взаимодействие с attributeChangedCallback и observedAttributes. Это делает код более декларативным, безопасным и удобным для типизации через TypeScript. Каждый prop автоматически валидируется и при необходимости конвертируется к указанному типу.


Atomico превращает работу с props в единый, реактивный и типизированный инструмент, который сочетает удобство JSX и мощь веб-компонентов. Это позволяет строить масштабируемые и предсказуемые UI, где свойства компонентов строго контролируются и легко интегрируются с DOM и состоянием.