Atomico — современная библиотека для создания веб-компонентов на JavaScript, обеспечивающая удобный и декларативный подход к построению UI. Одной из ключевых возможностей веб-компонентов является использование Shadow DOM, который обеспечивает инкапсуляцию стилей и структуры компонента.
Shadow DOM создаёт отдельное DOM-дерево внутри
компонента, изолированное от основного документа. Элементы в shadow root
не наследуют стили родительского документа, а внешние стили не влияют на
содержимое компонента, если не используется механизм ::part
или ::slotted.
Основные преимущества Shadow DOM:
Atomico использует функцию c для создания компонента и
автоматически управляет shadow root. При этом DOM-компонент создается в
shadow root по умолчанию, что упрощает работу с инкапсуляцией.
Пример базового компонента с shadow DOM:
import { c, html, css } from "atomico";
const buttonStyles = css`
button {
background-color: #007acc;
color: white;
border: none;
padding: 10px 20px;
border-radius: 4px;
cursor: pointer;
}
`;
function Button() {
return html`
<button>Click me</button>
`;
}
Button.styles = buttonStyles;
customElements.define("my-button", c(Button));
В этом примере:
Button оборачивается в shadow
root автоматически.Button.styles и применяются
только внутри компонента.button.slots и
::slottedShadow DOM поддерживает слоты, позволяя вставлять внешнее содержимое в компонент. В Atomico слоты используются так же, как и в стандартных веб-компонентах:
function Card() {
return html`
<div class="card">
<slot name="header"></slot>
<div class="content">
<slot></slot>
</div>
</div>
`;
}
Card.styles = css`
.card {
border: 1px solid #ccc;
padding: 16px;
border-radius: 8px;
}
::slotted([slot="header"]) {
font-weight: bold;
font-size: 18px;
margin-bottom: 8px;
}
`;
Применение в HTML:
<my-card>
<h2 slot="header">Заголовок карточки</h2>
<p>Основной контент карточки</p>
</my-card>
slot="header" будет стилизован через
::slotted..content.Atomico поддерживает реактивные свойства, что позволяет динамически изменять содержимое внутри shadow root, сохраняя инкапсуляцию.
import { c, html, useState, css } from "atomico";
function Toggle() {
const [on, setOn] = useState(false);
return html`
<button oncl ick=${() => setOn(!on)}>
${on ? "Включено" : "Выключено"}
</button>
`;
}
Toggle.styles = css`
button {
padding: 10px;
border-radius: 5px;
border: 1px solid #333;
}
`;
customElements.define("my-toggle", c(Toggle));
useState, что обеспечивает
реактивность компонентов.Shadow DOM в Atomico облегчает композицию компонентов, так как каждый компонент полностью изолирован:
function App() {
return html`
<my-card>
<h2 slot="header">Пример карточки</h2>
<my-toggle></my-toggle>
</my-card>
`;
}
my-toggle работает независимо внутри
my-card.my-card не влияют на my-toggle и
наоборот.Использование shadow DOM в Atomico позволяет строить компоненты с чёткой границей ответственности:
Такой подход обеспечивает надежное, предсказуемое поведение компонентов и делает архитектуру приложения более модульной.