FAST Element — это современная библиотека для создания веб-компонентов с высокой производительностью и удобным API. Одной из ключевых задач при разработке на FAST Element является повторное использование логики без дублирования кода. Существуют несколько подходов, которые позволяют структурировать компоненты так, чтобы бизнес-логика была модульной, легко тестируемой и расширяемой.
Миксины в FAST Element позволяют добавлять общую функциональность нескольким компонентам без использования наследования от одного базового класса. Они реализуются через функции, которые принимают класс и возвращают новый класс с расширенными возможностями.
Пример:
import { FASTElement, html, css } from "@microsoft/fast-element";
function Focusable(Base) {
return class extends Base {
focus() {
this.shadowRoot?.querySelector('input')?.focus();
}
};
}
class MyInput extends Focusable(FASTElement) {
value = "";
}
MyInput.define({
name: "my-input",
template: html`<input type="text" :value="${x => x.value}">`,
styles: css`input { border: 1px solid #ccc; padding: 4px; }`
});
Ключевой момент: миксины помогают добавлять повторяющуюся логику без необходимости создавать сложные иерархии классов.
Для изоляции логики, не зависящей от DOM-компонента, удобно использовать отдельные классы-утилиты. Такой подход полезен для обработки данных, валидации, работы с API и других задач, которые могут использоваться в нескольких компонентах.
Пример:
export class Validator {
static isEmail(value) {
return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(value);
}
static isNotEmpty(value) {
return value.trim().length > 0;
}
}
// Использование в компоненте
import { Validator } from './validator.js';
class EmailInput extends FASTElement {
email = "";
validate() {
return Validator.isEmail(this.email);
}
}
Ключевой момент: логика отделена от визуального представления, что облегчает тестирование и повторное использование.
FAST Element поддерживает повторное использование шаблонов через template fragments и composition. Это позволяет создавать переиспользуемые блоки UI, не дублируя разметку.
Пример:
import { html } from "@microsoft/fast-element";
export const labelTemplate = html`
<label :for="${x => x.for}">${x => x.text}</label>
`;
class TextInput extends FASTElement {
for = "input1";
text = "Введите текст:";
}
TextInput.define({
name: "text-input",
template: html`${labelTemplate}<input id="${x => x.for}" type="text">`
});
Ключевой момент: один и тот же шаблон можно использовать в нескольких компонентах, меняя только данные через привязку.
Контроллеры в FAST Element позволяют вынести часть поведения компонента в отдельный объект. Это особенно полезно для сложной логики обработки событий, подписок на изменения данных или интеграции с внешними сервисами.
Пример:
import { FASTElement, html, Observable, FASTElementController } from "@microsoft/fast-element";
class TooltipController {
constructor(element) {
this.element = element;
this.show = false;
}
toggle() {
this.show = !this.show;
this.element.requestUpdate();
}
}
class ButtonWithTooltip extends FASTElement {
tooltipController;
connectedCallback() {
super.connectedCallback();
this.tooltipController = new TooltipController(this);
}
}
ButtonWithTooltip.define({
name: "button-tooltip",
template: html`
<button @click="${x => x.tooltipController.toggle()}">Hover me</button>
<div ?hidden="${x => !x.tooltipController.show}">Подсказка</div>
`
});
Ключевой момент: контроллер позволяет вынести повторяемую логику в отдельный объект, который можно применять к разным компонентам без копирования кода.
Наследование в FAST Element применяется реже, но оно эффективно для создания иерархии компонентов с общими базовыми свойствами и методами. Базовый компонент может содержать общую логику, а дочерние компоненты — только специфическую часть.
Пример:
class BaseInput extends FASTElement {
value = "";
handleChange(e) {
this.value = e.target.value;
}
}
class PasswordInput extends BaseInput {}
PasswordInput.define({
name: "password-input",
template: html`<input type="password" :value="${x => x.value}" @input="${x => x.handleChange($event)}">`
});
Ключевой момент: наследование упрощает повторное использование базовой функциональности, но может привести к жесткой связности между компонентами, поэтому рекомендуется комбинировать с миксинами и контроллерами.
FAST Element предоставляет мощную систему реактивных свойств, которая позволяет автоматически отслеживать изменения данных и минимизировать дублирование логики по обновлению UI.
import { FASTElement, html, observable } from "@microsoft/fast-element";
class TodoList extends FASTElement {
@observable items = [];
addItem(item) {
this.items = [...this.items, item];
}
removeItem(index) {
this.items = this.items.filter((_, i) => i !== index);
}
}
TodoList.define({
name: "todo-list",
template: html`
<ul>
${x => x.items.map(item => html`<li>${item}</li>`)}
</ul>
`
});
Ключевой момент: реактивные свойства позволяют отделить логику изменения данных от шаблона, что делает код компонентов более чистым и модульным.
На практике для больших проектов часто используется смешанный подход:
Такой подход обеспечивает максимальную модульность, тестируемость и поддерживаемость компонентов.
FAST Element предоставляет гибкие инструменты для повторного использования логики, позволяя строить сложные интерфейсы с минимальным дублированием кода и высокой степенью переиспользуемости.