В JavaScript-фреймворке Lit построение компонентов возможно через два основных подхода: наследование и композицию. Каждый из них имеет свои преимущества и ограничения, и понимание различий критически важно для построения масштабируемых интерфейсов.
Наследование в Lit осуществляется через стандартные механизмы классов
JavaScript. Компонент создается как класс, который расширяет базовый
класс LitElement или другой пользовательский компонент.
import { LitElement, html, css } from 'lit';
class BaseButton extends LitElement {
static styles = css`
button {
padding: 8px 16px;
border-radius: 4px;
border: none;
cursor: pointer;
}
`;
render() {
return html``;
}
}
class PrimaryButton extends BaseButton {
static styles = [
BaseButton.styles,
css`
button {
background-color: blue;
color: white;
}
`
];
}
customElements.define('primary-button', PrimaryButton);
Особенности наследования:
Композиция предполагает создание компонентов как независимых единиц, которые могут включать друг друга через разметку. В Lit это делается с помощью включения одного компонента внутрь другого.
import { LitElement, html, css } from 'lit';
import './primary-button.js';
class DialogBox extends LitElement {
static styles = css`
.dialog {
border: 1px solid #ccc;
padding: 16px;
border-radius: 8px;
width: 300px;
}
`;
render() {
return html`
Ок
`;
}
}
customElements.define('dialog-box', DialogBox);
Особенности композиции:
| Характеристика | Наследование | Композиция |
|---|---|---|
| Повторное использование | Да, через базовые классы | Да, через включение компонентов |
| Изоляция логики | Низкая (зависимость от базового класса) | Высокая (каждый компонент автономен) |
| Гибкость | Ограничена иерархией | Высокая, можно комбинировать как угодно |
| Масштабируемость | Сложнее при глубокой иерархии | Легче, благодаря модульности |
В Lit композиция тесно связана с передачей данных через
свойства (@property) и обработку событий
через CustomEvent:
class CounterButton extends LitElement {
static properties = {
count: { type: Number }
};
constructor() {
super();
this.count = 0;
}
_increment() {
this.count++;
this.dispatchEvent(new CustomEvent('count-changed', { detail: this.count }));
}
render() {
return html``;
}
}
customElements.define('counter-button', CounterButton);
Другой компонент может использовать этот элемент:
class Dashboard extends LitElement {
render() {
return html`
console.log(e.detail)}>
`;
}
}
customElements.define('dashboard-view', Dashboard);
Такой подход обеспечивает максимальную гибкость и контроль без необходимости глубокого наследования.