Lit — лёгкий и современный фреймворк для создания веб-компонентов на основе стандартов платформы. Он особенно хорошо подходит для построения компонентных библиотек и Design System благодаря минимализму, высокой производительности и строгой опоре на Web Components API.
В основе Lit лежат кастомные элементы (Custom Elements) и шаблоны на основе tagged template literals. Это означает, что каждый компонент является полноценным HTML-элементом, зарегистрированным в браузере и изолированным от остального DOM.
Ключевые строительные блоки:
LitElement — базовый класс для компонентовhtml — функция для описания шаблоновТакой подход позволяет создавать компоненты, которые:
Компонент в Lit — это класс, расширяющий LitElement:
import { LitElement, html, css } from 'lit';
export class MyButton extends LitElement {
static properties = {
disabled: { type: Boolean }
};
static styles = css`
button {
padding: 8px 16px;
border-radius: 4px;
}
`;
render() {
return html`
<button ?disabled=${this.disabled}>
<slot></slot>
</button>
`;
}
}
customElements.define('my-button', MyButton);
Здесь отражены ключевые идеи Lit:
Lit использует реактивность на уровне свойств класса. Любое изменение реактивного свойства автоматически инициирует обновление DOM.
static properties = {
value: { type: String },
count: { type: Number, reflect: true }
};
Особенности:
type управляет преобразованием атрибут ↔︎ свойствоreflect: true синхронизирует свойство с
HTML-атрибутомLit использует fine-grained diffing на уровне шаблона, а не всего компонента. Это снижает количество операций с DOM и делает обновления предсказуемыми.
Шаблоны в Lit основаны на tagged template literals:
html`<p>${this.value}</p>`
${this.visible ? html`<div>Content</div>` : null}
import { repeat } from 'lit/directives/repeat.js';
${repeat(this.items, item => item.id, item =>
html`<li>${item.label}</li>`
)}
Директивы позволяют расширять шаблоны без усложнения логики компонента. Для Design System это критично — шаблоны должны оставаться читаемыми и стабильными.
Каждый компонент Lit по умолчанию использует Shadow DOM. Это обеспечивает:
static styles = css`
:host {
display: inline-block;
}
`;
Для Design System особенно важно использовать CSS-переменные как основной механизм кастомизации:
button {
background: var(--ds-button-bg, #005fcc);
color: var(--ds-button-color, #fff);
}
Такой подход:
Слоты — основной механизм композиции в Lit-компонентах:
<my-card>
<h2 slot="title">Заголовок</h2>
<p>Контент</p>
</my-card>
render() {
return html`
<div class="card">
<slot name="title"></slot>
<slot></slot>
</div>
`;
}
Для компонентных библиотек это позволяет:
Lit не навязывает собственную систему событий. Используются стандартные DOM Events.
this.dispatchEvent(new CustomEvent('change', {
detail: { value: this.value },
bubbles: true,
composed: true
}));
Параметры bubbles и composed важны для
Design System:
Lit одинаково хорошо поддерживает оба подхода:
Пример гибридного подхода:
updated(changedProps) {
if (changedProps.has('value')) {
this.internalValue = this.value;
}
}
Это позволяет адаптировать компоненты под разные сценарии использования в Design System.
Lit оптимизирован для частых обновлений:
requestUpdate для ручного контроляthis.requestUpdate('value', oldValue);
Для сложных библиотек это даёт возможность:
Lit особенно хорошо подходит для Design System по следующим причинам:
Стандарты платформы
Независимость
Чёткие контракты
Долгосрочная поддержка
Типичная структура:
components/
button/
button.ts
button.styles.ts
input/
modal/
tokens/
colors.css
spacing.css
Рекомендации:
Lit занимает нишу фундаментального инструмента для создания компонентных библиотек и Design System. Он не конкурирует с фреймворками приложений, а дополняет их, предоставляя стабильный, предсказуемый и стандартизированный слой UI-компонентов.