Shadow DOM является ключевым инструментом для изоляции стилей и структуры компонентов в Atomico. Каждый компонент создаёт собственный теневой корень, что позволяет отделить внутренние элементы от глобального контекста документа. Это обеспечивает:
document.querySelector.В Atomico создание Shadow DOM осуществляется автоматически при
использовании функции component. Например:
import { component, html } from "atomico";
function MyButton() {
return html`
<button>Нажми меня</button>
`;
}
customElements.define("my-button", component(MyButton));
По умолчанию создается теневой корень с режимом
open, что позволяет получить доступ к внутреннему
DOM через shadowRoot, если это необходимо для
интеграции.
Рендеринг Shadow DOM может стать узким местом при сложных интерфейсах. Atomico предоставляет несколько приёмов для оптимизации:
Функция useState и реактивные свойства
(props) создают триггеры на обновление компонента.
Перерисовка всего Shadow DOM происходит только при изменении значений,
от которых зависит шаблон.
import { component, html, useState } from "atomico";
function Counter() {
const [count, setCount] = useState(0);
return html`
<button oncl ick=${() => setCount(count + 1)}>
${count}
</button>
`;
}
Совет: избегать включения в шаблон вычислений, которые не зависят от состояния, так как они будут выполняться при каждой перерисовке.
Для сложных компонентов, содержащих множество вложенных элементов,
можно использовать условный рендеринг с if:
return html`
${showContent ? html`<div>Загружено</div>` : html``}
`;
Это позволяет уменьшить количество элементов в Shadow DOM до момента их реального использования.
Многоуровневый Shadow DOM усложняет обновления. Разделение крупных компонентов на маленькие Atomico-компоненты с собственными теневыми корнями повышает локальную изоляцию обновлений, снижая нагрузку на главный компонент.
В Atomico стили можно подключать напрямую через шаблон:
return html`
<style>
button {
background: #3498db;
color: white;
}
</style>
<button>Кнопка</button>
`;
События внутри Shadow DOM по умолчанию изолированы. Чтобы они
всплывали наружу, используется composed: true:
const button = document.createElement("button");
button.addEventListener("click", (e) => console.log("Clicked"));
button.dispatchEvent(new Event("click", { bubbles: true, composed: true }));
Atomico автоматически поддерживает связь событий через свойства, но при массовых обновлениях стоит использовать делегирование, чтобы не создавать лишние обработчики внутри Shadow DOM.
Иногда требуется обратиться к теневому корню компонента:
const elem = document.querySelector("my-button");
const shadow = elem.shadowRoot;
Рекомендация: ограничивать прямой доступ к Shadow DOM, чтобы сохранить изоляцию и снизить вероятность ненужных перерисовок или конфликтов стилей.
open — позволяет внешнему коду обращаться к
shadowRoot.closed — полностью изолирует внутренние элементы. В
Atomico по умолчанию используется open, но для критических
компонентов можно применять closed для повышения
безопасности и предотвращения вмешательства.Atomico поддерживает мемоизацию шаблонов через обычные JS-паттерны:
import { memo } from "atomico";
const HeavyContent = memo(() => html`<div>Тяжёлый контент</div>`);
useState.composed и
делегирование.Эти методы обеспечивают эффективное управление Shadow DOM, повышают производительность и поддерживают чистоту кода при создании сложных веб-компонентов в Atomico.