В Mithril компоненты могут быть реализованы либо как простые объекты
с методами view и опциональными хуками, либо как классы.
Классовые компоненты позволяют организовать код более структурированно,
особенно при сложной логике и необходимости управления состоянием.
Класс-компонент в Mithril — это ES6-класс с методом
view. Конструктор класса используется для инициализации
состояния и создания внутренних переменных. Пример базового класса:
class Counter {
constructor() {
this.count = 0;
}
view() {
return m("div", [
m("p", `Счётчик: ${this.count}`),
m("button", { onclick: () => this.count++ }, "Увеличить")
]);
}
}
В этом примере свойство count является внутренним
состоянием компонента. Кнопка увеличивает его значение, а Mithril
автоматически обновляет виртуальный DOM при изменении состояния через
события.
Mithril предоставляет набор специальных методов, которые вызываются на различных этапах жизни компонента. Классовые компоненты могут реализовывать следующие методы жизненного цикла:
oninit(vnode)Вызывается один раз при инициализации компонента перед его первым рендером. Используется для настройки начального состояния или выполнения асинхронных операций.
class UserProfile {
oninit(vnode) {
this.user = null;
fetch("/api/user")
.then(response => response.json())
.then(data => this.user = data);
}
view() {
return m("div", this.user ? `Привет, ${this.user.name}` : "Загрузка...");
}
}
oncreate(vnode)Вызывается после того, как элемент был вставлен в DOM. Позволяет взаимодействовать с реальным DOM, запускать анимации или интегрироваться с внешними библиотеками.
class Tooltip {
oncreate(vnode) {
this.element = vnode.dom;
this.element.title = "Подсказка";
}
view() {
return m("button", "Наведите на меня");
}
}
onupdate(vnode)Вызывается после обновления DOM компонента. Позволяет реагировать на изменения состояния, синхронизировать данные или перезапускать анимации.
class AutoFocusInput {
onupdate(vnode) {
if (!vnode.state.focused) {
vnode.dom.focus();
vnode.state.focused = true;
}
}
view(vnode) {
return m("input", { type: "text" });
}
}
onbeforeupdate(vnode, old)Вызывается перед обновлением компонента. Возвращение
false предотвращает обновление компонента. Полезно для
оптимизации производительности.
class ExpensiveComponent {
onbeforeupdate(vnode, old) {
return vnode.attrs.value !== old.attrs.value;
}
view(vnode) {
return m("p", `Значение: ${vnode.attrs.value}`);
}
}
onbeforeremove(vnode)Вызывается перед удалением элемента из DOM. Можно использовать для запуска анимаций ухода или очистки таймеров. Возвращаемый промис задерживает удаление до завершения асинхронной операции.
class FadeOut {
onbeforeremove(vnode) {
return new Promise(resolve => {
vnode.dom.style.transition = "opacity 0.5s";
vnode.dom.style.opacity = 0;
setTimeout(resolve, 500);
});
}
view() {
return m("div", "Элемент исчезает плавно");
}
}
onremove(vnode)Вызывается после того, как элемент был удалён из DOM. Используется для окончательной очистки ресурсов.
class CleanupTimer {
onremove(vnode) {
clearInterval(vnode.state.timer);
}
oninit(vnode) {
vnode.state.timer = setInterval(() => console.log("Тик"), 1000);
}
view() {
return m("div", "Таймер работает");
}
}
Классовые компоненты в Mithril разделяют два источника данных:
state) — внутренние
свойства класса, управляемые самим компонентом. Обычно инициализируются
в конструкторе или oninit.attrs) — данные, переданные
компоненту извне через vnode. Эти значения доступны через
vnode.attrs и должны рассматриваться как неизменяемые
внутри компонента.class Greeting {
view(vnode) {
return m("p", `Привет, ${vnode.attrs.name}`);
}
}
Изменения атрибутов со стороны родительского компонента вызывают
повторный рендер дочернего компонента, автоматически вызывая методы
жизненного цикла onbeforeupdate и
onupdate.
oninit — для асинхронных
данных.view —
логика рендера должна быть чистой, без прямого обращения к DOM.onbeforeupdate для предотвращения лишних рендеров.onbeforeremove и onremove для очистки
таймеров, подписок и внешних библиотек.Классовые компоненты с методами жизненного цикла в Mithril обеспечивают полный контроль над поведением и состоянием компонентов, позволяя создавать сложные интерактивные интерфейсы с минимальными накладными расходами и высокой производительностью.