Классовые компоненты и методы жизненного цикла

В 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.


Рекомендации по организации классовых компонентов

  1. Инициализация состояния — использовать конструктор для создания локальных свойств, oninit — для асинхронных данных.
  2. Минимизация побочных эффектов в view — логика рендера должна быть чистой, без прямого обращения к DOM.
  3. Разделение ответственности — сложные компоненты делить на мелкие, чтобы каждый класс управлял одной функциональностью.
  4. Оптимизация обновлений — применять onbeforeupdate для предотвращения лишних рендеров.
  5. Управление ресурсами — использовать onbeforeremove и onremove для очистки таймеров, подписок и внешних библиотек.

Классовые компоненты с методами жизненного цикла в Mithril обеспечивают полный контроль над поведением и состоянием компонентов, позволяя создавать сложные интерактивные интерфейсы с минимальными накладными расходами и высокой производительностью.