Lit — современный фреймворк для создания Web Components, ориентированный на декларативное описание UI с высокой производительностью. В React-приложениях Lit-компоненты используются как нативные HTML-элементы, что позволяет сочетать преимущества React и возможности веб-компонентов: переиспользуемость, инкапсуляцию стилей и легковесность.
Для интеграции достаточно импортировать класс компонента и
зарегистрировать его через customElements.define. После
этого компонент можно использовать в JSX точно так же, как любой
HTML-тег:
import { LitElement, html, css } from 'lit';
class MyButton extends LitElement {
static styles = css`
button {
padding: 10px 20px;
background-color: #6200ea;
color: white;
border: none;
border-radius: 4px;
cursor: pointer;
}
`;
render() {
return html`<button><slot></slot></button>`;
}
}
customElements.define('my-button', MyButton);
function App() {
return <my-button>Нажми меня</my-button>;
}
Lit-компоненты поддерживают реактивные свойства через декоратор
@property. Для корректной работы с React важно учитывать,
что React передаёт пропсы как обычные HTML-атрибуты, поэтому свойства
должны быть синхронизированы с атрибутами:
import { LitElement, html } from 'lit';
import { property } from 'lit/decorators.js';
class CounterElement extends LitElement {
@property({ type: Number })
count = 0;
render() {
return html`<div>Счётчик: ${this.count}</div>`;
}
}
customElements.define('counter-element', CounterElement);
В React:
function App() {
return <counter-element count={5}></counter-element>;
}
Для передачи событий используется CustomEvent. В React
подключение событий через on<Event> работает только с
кастомной обработкой, так как React не автоматически подписывается на
addEventListener веб-компонентов:
class CounterElement extends LitElement {
@property({ type: Number }) count = 0;
increment() {
this.count++;
this.dispatchEvent(new CustomEvent('count-changed', { detail: this.count }));
}
render() {
return html`<button @click=${this.increment}>${this.count}</button>`;
}
}
customElements.define('counter-element', CounterElement);
В React обработка события:
function App() {
const handleCountChange = (e) => {
console.log('Новый счёт:', e.detail);
};
return <counter-element onCountChan ged={handleCountChange}></counter-element>;
}
Lit использует Shadow DOM для инкапсуляции стилей. Это позволяет избежать конфликтов с глобальными CSS React-приложения. Для передачи внешних стилей можно использовать CSS-переменные:
class StyledElement extends LitElement {
static styles = css`
div {
color: var(--text-color, black);
font-size: 16px;
}
`;
render() {
return html`<div>Текст с кастомной стилизацией</div>`;
}
}
customElements.define('styled-element', StyledElement);
В React:
function App() {
return <styled-element style={{ '--text-color': 'red' }}></styled-element>;
}
Для интеграции реактивности React с Lit-компонентами можно
использовать useRef для доступа к элементу и вызова его
методов:
import { useRef, useEffect } from 'react';
function App() {
const counterRef = useRef(null);
useEffect(() => {
if (counterRef.current) {
counterRef.current.count = 10;
}
}, []);
return <counter-element ref={counterRef}></counter-element>;
}
Это позволяет управлять внутренним состоянием веб-компонента из React и комбинировать реактивные механизмы обоих фреймворков.
Lit имеет минимальный overhead благодаря шаблонной системе и реактивным свойствам. В React-приложениях важно учитывать:
React.memo для контейнеров с
Lit-компонентами, если их состояние редко меняется.ref для глубоких структур
данных.<slot> внутри Lit.className,
htmlFor) должны быть заменены на стандартные HTML-атрибуты
(class, for) при работе с Lit.Использование Lit в React позволяет создавать высокопроизводительные и инкапсулированные компоненты с современными возможностями Web Components, сохраняя привычную архитектуру React-приложения.