Atomico — современная библиотека для создания веб-компонентов с реактивностью, схожей с React, но полностью основанная на стандартах Web Components. Одним из ключевых подходов в организации компонентов является разделение на Presentational и Container компоненты. Этот подход позволяет строить архитектуру приложения более чистой, понятной и переиспользуемой.
Presentational (или “декоративные”) компоненты отвечают только за отображение данных и пользовательский интерфейс. Они:
В Atomico Presentational компонент определяется функцией,
возвращающей JSX-подобный синтаксис с использованием
html:
import { c, html } from "atomico";
function Button({ label, onClick }) {
return html`
<button oncl ick=${onClick}>${label}</button>
`;
}
Button.props = {
label: String,
onClick: Function
};
export const button = c(Button);
Ключевой момент: компонент не использует локальное состояние
(useState) и не зависит от внешних сервисов. Он полностью
управляется данными, которые ему передают родительские компоненты.
Container (или “умные”) компоненты отвечают за логику приложения, управление состоянием и получение данных. Их функции:
useState или
useStore;useEffect;Пример Container компонента в Atomico:
import { c, html, useState, useEffect } from "atomico";
import { button } from "./Button";
function CounterContainer() {
const [count, setCount] = useState(0);
function increment() {
setCount(count + 1);
}
return html`
<div>
<p>Текущее значение: ${count}</p>
<${button} label="Увеличить" onCl ick=${increment} />
</div>
`;
}
export const counterContainer = c(CounterContainer);
Здесь видно, что CounterContainer управляет состоянием
count и передает его в Presentational компонент
Button. Такая структура позволяет отделить визуальную часть
от логики, облегчая тестирование и поддержку.
Основная идея подхода:
Преимущества:
Presentational компоненты в Atomico используют:
emit) для уведомления
Container о действиях пользователя.Пример передачи события:
import { c, html } from "atomico";
function Input({ value, onInput }) {
return html`<input value=${value} onIn put=${(e) => onInput(e.target.value)} />`;
}
Input.props = {
value: String,
onInput: Function
};
export const input = c(Input);
Container может использовать его так:
import { c, html, useState } from "atomico";
import { input } from "./Input";
function FormContainer() {
const [text, setText] = useState("");
return html`
<div>
<${input} value=${text} onIn put=${setText} />
<p>Вы ввели: ${text}</p>
</div>
`;
}
export const formContainer = c(FormContainer);
Эта схема гарантирует, что Presentational компонент остается чистым и независимым, а Container берет на себя всю сложную логику.
Разделение на Presentational и Container компоненты в Atomico:
Atomico предоставляет все инструменты для строгого соблюдения этого
паттерна: реактивность через useState и
useEffect, декларативный синтаксис через html,
удобную работу с props и событиями. Это позволяет строить приложения с
четкой архитектурой и минимальными связями между слоями логики и
представления.