Порядок выполнения методов

В фреймворке Stimulus жизненный цикл контроллера организован так, чтобы разработчик имел строгий контроль над инициализацией и поведением компонентов. Контроллер Stimulus — это класс, который расширяет Controller и привязывается к элементу DOM через атрибут data-controller. Жизненный цикл контроллера включает несколько ключевых методов: initialize, connect, disconnect и дополнительные методы для наблюдения за изменениями.

Метод initialize

Метод initialize вызывается один раз в момент создания экземпляра контроллера, до того как элемент будет подключен к DOM. На этом этапе доступна ссылка на элемент this.element, но DOM-дерево может быть ещё не полностью готово для манипуляций. Основные задачи метода:

  • Инициализация внутренних свойств контроллера.
  • Создание вспомогательных структур данных.
  • Настройка начальных состояний без обращения к потомкам элемента.

Пример:

import { Controller } from "@hotwired/stimulus"

export default class extends Controller {
  initialize() {
    this.counter = 0
    console.log("Контроллер создан, DOM может быть ещё не готов")
  }
}

Метод connect

Метод connect вызывается каждый раз, когда элемент появляется в DOM. Это основной момент для взаимодействия с интерфейсом, подписок на события и активации сторонних библиотек. Если элемент был временно удалён из DOM и возвращён, connect будет вызван повторно.

Основные действия в connect:

  • Привязка событий к элементам.
  • Запуск анимаций или сторонних библиотек.
  • Инициализация видимой части UI.

Пример:

connect() {
  this.element.addEventListener("click", this.increment.bind(this))
  console.log("Элемент подключён к DOM")
}

increment() {
  this.counter++
  console.log(`Счётчик: ${this.counter}`)
}

Метод disconnect

Метод disconnect вызывается при удалении элемента из DOM. Он предназначен для очистки ресурсов и предотвращения утечек памяти. Любые подписки на события, таймеры или сторонние объекты следует освобождать именно здесь.

Пример:

disconnect() {
  this.element.removeEventListener("click", this.increment)
  console.log("Элемент удалён из DOM, подписки очищены")
}

Методы refresh и reconnect

Stimulus также поддерживает динамическое управление элементами. Если элемент перемещается внутри DOM, контроллер может быть автоматически отключен и подключён заново, что позволяет обновить привязки.

  • reconnect() — вручную можно вызвать повторное подключение контроллера к элементу.
  • refresh() — обновляет значения и связи с элементами, особенно полезно при динамических изменениях DOM через сторонние библиотеки.

Порядок выполнения методов

  1. Создание экземпляра контроллера: вызывается конструктор, затем initialize.
  2. Первичное подключение к DOM: connect.
  3. Удаление из DOM: disconnect.
  4. Повторное подключение (если элемент возвращён): connect снова.

Важно учитывать, что initialize вызывается только один раз за жизненный цикл экземпляра, а connect и disconnect могут вызываться многократно при динамических изменениях DOM.

Принципы работы с жизненным циклом

  • Все свойства, которые нужны для работы контроллера, следует инициализировать в initialize.
  • Любые операции с DOM лучше выполнять в connect, так как на этом этапе элемент гарантированно присутствует в документе.
  • Любые подписки, таймеры и сторонние ресурсы должны быть очищены в disconnect для предотвращения утечек памяти.
  • Если контроллер работает с динамическими элементами, важно учитывать, что connect может быть вызван повторно, а внутренние состояния необходимо корректно синхронизировать.

Пример полного контроллера с полным циклом

import { Controller } from "@hotwired/stimulus"

export default class extends Controller {
  initialize() {
    this.counter = 0
    console.log("Контроллер инициализирован")
  }

  connect() {
    this.element.addEventListener("click", this.increment.bind(this))
    console.log("Контроллер подключён")
  }

  disconnect() {
    this.element.removeEventListener("click", this.increment)
    console.log("Контроллер отключён")
  }

  increment() {
    this.counter++
    this.element.textContent = `Счётчик: ${this.counter}`
  }
}

Такой подход обеспечивает чёткий контроль над жизненным циклом, позволяет безопасно работать с динамическим DOM и гарантирует предсказуемое поведение компонентов.