Lit — это современный фреймворк для создания веб-компонентов на JavaScript, обеспечивающий высокую производительность и удобство работы с реактивными данными. Ключевым элементом Lit является класс LitElement, от которого наследуются все компоненты. Основная структура компонента выглядит следующим образом:
import { LitElement, html, css } from 'lit';
class MyComponent extends LitElement {
static styles = css`
:host {
display: block;
padding: 16px;
background-color: #f0f0f0;
}
p {
color: #333;
}
`;
static properties = {
title: { type: String },
count: { type: Number },
};
constructor() {
super();
this.title = 'Пример компонента';
this.count = 0;
}
render() {
return html`
<h1>${this.title}</h1>
<p>Счетчик: ${this.count}</p>
<button @click=${() => this.count++}>Увеличить</button>
`;
}
}
customElements.define('my-component', MyComponent);
Ключевые моменты:
@click) связывают DOM с
методами класса без прямого использования addEventListener.Lit использует реактивную модель: любое изменение свойства,
объявленного в static properties, вызывает повторный рендер
компонента. Это позволяет строить динамические интерфейсы без ручного
управления DOM. Важно понимать различие между:
requestUpdate()
для принудительного рендера.Пример:
this.items = [...this.items, newItem]; // создается новый массив, триггерится обновление
this.requestUpdate(); // принудительное обновление, если объект изменен мутацией
Lit использует шаблоны HTML, встроенные в JavaScript
с помощью html. Для управления динамикой применяются
директивы:
repeat — для рендеринга списков:import { repeat } from 'lit/directives/repeat.js';
render() {
return html`
<ul>
${repeat(this.items, item => item.id, item => html`<li>${item.name}</li>`)}
</ul>
`;
}
ifDefined — для условной вставки
атрибутов:import { ifDefined } from 'lit/directives/if-defined.js';
html`<img src=${ifDefined(this.imageUrl)} />`
classMap и styleMap —
динамическое управление классами и стилями:import { classMap } from 'lit/directives/class-map.js';
html`<div class=${classMap({ active: this.isActive, disabled: !this.isEnabled })}></div>`
Lit поддерживает слоты для создания гибких и переиспользуемых компонентов. Слоты позволяют вставлять произвольный HTML внутрь компонента:
render() {
return html`
<section>
<header><slot name="header"></slot></header>
<main><slot></slot></main>
<footer><slot name="footer"></slot></footer>
</section>
`;
}
Использование:
<my-component>
<h1 slot="header">Заголовок</h1>
<p>Основной контент</p>
<small slot="footer">Подвал</small>
</my-component>
Для крупных проектов Lit компоненты должны проходить непрерывную интеграцию (Continuous Integration, CI). Основные шаги:
vite или
rollup для генерации продакшн-бандла.@web/test-runner совместно с @open-wc/testing
позволяет писать юнит- и интеграционные тесты для веб-компонентов.Storybook или
Lit DevTools помогают документировать компоненты и
визуально проверять состояния.Пример конфигурации GitHub Actions для CI:
name: CI
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Setup Node.js
uses: actions/setup-node@v3
with:
node-version: '20'
- run: npm ci
- run: npm run lint
- run: npm run test
- run: npm run build
Пример теста с @open-wc/testing:
import { fixture, html, expect } from '@open-wc/testing';
import './my-component.js';
describe('MyComponent', () => {
it('рендерит заголовок', async () => {
const el = await fixture(html`<my-component title="Тест"></my-component>`);
expect(el.shadowRoot.querySelector('h1').textContent).to.equal('Тест');
});
});
Lit применяет shady DOM и shadow DOM для изоляции стилей и минимизации перерисовок. Для повышения производительности:
shouldUpdate(changedProps) для контроля
обновлений.cache для сохранения шаблонов,
которые редко меняются.Пример:
import { cache } from 'lit/directives/cache.js';
render() {
return html`${cache(this.isLoaded ? html`<p>Загружено</p>` : html`<p>Загрузка...</p>`)}`;
}
Типичная структура:
src/
components/
my-component.js
styles/
variables.css
index.js
tests/
my-component.test.js
public/
index.html
vite.config.js
package.json
Эта организация упрощает интеграцию в CI/CD и масштабирование больших проектов.