Atomico — это современная библиотека для создания веб-компонентов на JavaScript, ориентированная на реактивное управление состоянием и оптимизацию производительности. Одной из ключевых возможностей является двусторонняя связь данных, позволяющая компонентам синхронизировать внутреннее состояние с внешними атрибутами или родительскими данными.
prop и
реактивностьОсновной механизм передачи данных в Atomico — это свойства
компонента (props). Свойства объявляются через функцию
props и могут быть реактивными:
import { c, useProp } from "atomico";
function MyComponent() {
const [value, setValue] = useProp("value", "");
return (
<input
value={value}
onIn put={event => setValue(event.target.value)}
/>
);
}
MyComponent.props = {
value: String
};
export default c(MyComponent);
В этом примере:
useProp("value", "") создаёт связку между внутренним
состоянием компонента и переданным свойством.value через setValue
автоматически отражается в DOM, а изменения извне компонента
синхронизируются с внутренним состоянием.Ключевой момент: useProp обеспечивает
двустороннюю реактивность, где изменения в компоненте и изменения
внешних данных остаются синхронизированными.
Для двусторонней связи с формами и элементами ввода удобно
использовать событие onInput или onChange, как
показано выше. Это позволяет создавать контролируемые
компоненты, где состояние поля ввода всегда соответствует
значению свойства.
function Checkbox({ checked, onChange }) {
return (
<input
type="checkbox"
checked={checked}
onCha nge={e => onChange(e.target.checked)}
/>
);
}
Для интеграции с Atomico можно использовать useProp:
function ControlledCheckbox() {
const [checked, setChecked] = useProp("checked", false);
return <Checkbox checked={checked} onCha nge={setChecked} />;
}
Atomico автоматически синхронизирует свойства компонента с HTML-атрибутами, что упрощает интеграцию с другими библиотеками и стандартными элементами DOM. При изменении значения свойства в компоненте соответствующий атрибут HTML обновляется и наоборот.
<MyComponent value="initial" />
Если внутри компонента произойдет изменение через
setValue, <my-component> получит
обновлённый атрибут value. Это особенно важно для создания
настраиваемых элементов, которые должны работать как обычные
HTML-теги.
useState и вычисляемых свойствДля сложных случаев двусторонней связи часто используют комбинацию
useState и useProp. useState
отвечает за локальное состояние, а useProp — за
синхронизацию с внешними данными:
import { c, useProp, useState } from "atomico";
function Counter() {
const [count, setCount] = useProp("count", 0);
const [double, setDouble] = useState(count * 2);
useEffect(() => {
setDouble(count * 2);
}, [count]);
return (
<div>
<button onCl ick={() => setCount(count - 1)}>-</button>
<span>{count}</span>
<button onCl ick={() => setCount(count + 1)}>+</button>
<p>Double: {double}</p>
</div>
);
}
Counter.props = {
count: Number
};
export default c(Counter);
Особенности:
useProp гарантирует, что внешнее свойство
count всегда синхронизировано с внутренним состоянием.double вычисляется на основе
count, обеспечивая реактивное обновление без необходимости
вмешательства извне.Для полноценной двусторонней связи компоненты часто используют пользовательские события:
function Input({ value, onChange }) {
return (
<input
value={value}
onIn put={e => onChange(e.target.value)}
/>
);
}
function App() {
const [text, setText] = useState("hello");
return <Input value={text} onCha nge={setText} />;
}
Atomico позволяет создавать и прослушивать пользовательские
события через dispatch, что расширяет возможности
двусторонней связи:
import { c, useProp, useHost } from "atomico";
function TextField() {
const [value, setValue] = useProp("value", "");
const host = useHost();
const handleInput = event => {
setValue(event.target.value);
host.dispatch("value-changed", { detail: event.target.value });
};
return <input value={value} onIn put={handleInput} />;
}
Здесь:
dispatch("value-changed", { detail }) уведомляет
родителя об изменении значения.props, лучше делать
простыми типами (строки, числа, булевы значения), чтобы
избежать сложной сериализации.useState внутри компонента и синхронизировать изменения
через события.props.useProp для реактивного
состояния.onInput,
onChange).dispatch для
уведомления родителя.useState для
производных данных.Такой подход обеспечивает полную синхронизацию между компонентами и внешним окружением, сохраняя простоту и предсказуемость работы веб-компонентов Atomico.