Declarative Shadow DOM — это современный подход к созданию теневого DOM, который позволяет предварительно определять структуру теневого дерева в HTML без необходимости программного создания элементов через JavaScript. В Lit это облегчает работу с компонентами, повышает производительность и улучшает поддержку серверного рендеринга.
Shadow DOM создаёт изолированное дерево элементов
внутри компонента, которое не наследует стили родительского документа.
Это позволяет избежать конфликтов CSS и JavaScript. До появления
Declarative Shadow DOM теневой DOM создавался программно через метод
attachShadow({ mode: 'open' }) и ручное добавление
элементов через шаблоны.
Declarative Shadow DOM переносит описание теневого дерева прямо в
HTML через <template shadowroot="open">. Этот шаблон
автоматически превращается в теневой DOM компонента при рендеринге.
Пример:
<my-element>
<template shadowroot="open">
<p>Теневой контент</p>
</template>
</my-element>
При загрузке страницы <p> окажется в теневом DOM
компонента <my-element>.
В Lit компоненты создаются через наследование от
LitElement или ReactiveElement. С внедрением
Declarative Shadow DOM можно использовать как стандартные методы
рендеринга, так и декларативные шаблоны.
import { LitElement, html, css } from 'lit';
class MyElement extends LitElement {
static styles = css`
p {
color: blue;
font-weight: bold;
}
`;
render() {
return html`
<p>Контент из Lit</p>
<template shadowroot="open">
<span>Теневой контент из шаблона</span>
</template>
`;
}
}
customElements.define('my-element', MyElement);
Особенности:
shadowroot принимает значения
"open" и "closed".<template> становится частью
теневого DOM и не виден в основном DOM.Стили, определённые в LitElement через
static styles, применяются только к теневому DOM
компонента. Declarative Shadow DOM полностью поддерживает этот
механизм.
import { LitElement, html, css } from 'lit';
class StyledElement extends LitElement {
static styles = css`
p {
color: red;
font-size: 18px;
}
`;
render() {
return html`
<template shadowroot="open">
<p>Красный текст в теневом DOM</p>
</template>
`;
}
}
customElements.define('styled-element', StyledElement);
Можно также использовать глобальные стили, но для изолированного
теневого DOM они не будут применяться автоматически. Для этого
необходимо включать стили вручную через <style>
внутри <template>.
Declarative Shadow DOM не ограничивает возможности динамического обновления. Через стандартные методы Lit можно менять содержимое теневого DOM, реагировать на события и связывать свойства.
import { LitElement, html } from 'lit';
class DynamicShadow extends LitElement {
static properties = {
message: { type: String }
};
constructor() {
super();
this.message = 'Привет';
}
render() {
return html`
<template shadowroot="open">
<p>${this.message}</p>
<button @click=${() => this.message = 'Обновлено'}>Обновить</button>
</template>
`;
}
}
customElements.define('dynamic-shadow', DynamicShadow);
Изменение свойства message автоматически обновляет
контент в теневом DOM.
<template shadowroot> создаётся один раз
при инициализации элемента и не может быть напрямую перемещён или
клонирован после рендеринга.<template>.Declarative Shadow DOM в Lit сочетает декларативный синтаксис HTML и реактивные возможности фреймворка, предоставляя мощный инструмент для создания современных веб-компонентов с изолированными стилями и предсказуемым поведением.