Stimulus — это JavaScript-фреймворк, ориентированный на добавление поведения к HTML через декларативные атрибуты. В его основе лежет концепция контроллеров, которые связывают DOM с логикой приложения. Центральной частью работы контроллера является реактивность: способность автоматически реагировать на изменения данных или состояния DOM без необходимости вручную отслеживать события.
Реактивность в Stimulus обеспечивается через:
Контроллер в Stimulus объявляется через класс, который наследуется от
Controller:
import { Controller } from "@hotwired/stimulus"
export default class extends Controller {
static targets = ["output"]
connect() {
console.log("Контроллер подключен")
}
updateOutput(value) {
this.outputTarget.textContent = value
}
}
static targets — массив строк, где
каждая строка указывает на элемент в DOM с соответствующим атрибутом
data-<controller>-target.this.<targetName>Target — доступ
к DOM-элементу, который автоматически «реактивно» связан с
контроллером.Изменения состояния в контроллере можно моментально отражать в DOM через методы контроллера. Stimulus отслеживает привязку к target и гарантирует корректную работу после подключения и отключения контроллера.
Value properties — это механизм для создания реактивных свойств контроллера. Они позволяют автоматически отслеживать изменения значений и выполнять связанные действия.
export default class extends Controller {
static values = { count: Number }
connect() {
console.log(`Начальное значение: ${this.countValue}`)
}
increment() {
this.countValue++
}
countValueChanged() {
console.log(`Новое значение: ${this.countValue}`)
}
}
Особенности:
static values — объявление свойств,
которые будут автоматически синхронизироваться с атрибутами DOM вида
data-<controller>-count-value.<property>ValueChanged — метод,
вызываемый автоматически при изменении значения свойства.Stimulus использует события DOM, чтобы реагировать на действия пользователя. Комбинируя value properties и targets, можно построить реактивные интерфейсы без лишнего кода.
Пример:
<div data-controller="counter" data-counter-count-value="0">
<span data-counter-target="output"></span>
<button data-action="click->counter#increment">Добавить</button>
</div>
export default class extends Controller {
static targets = ["output"]
static values = { count: Number }
connect() {
this.updateOutput()
}
increment() {
this.countValue++
}
countValueChanged() {
this.updateOutput()
}
updateOutput() {
this.outputTarget.textContent = this.countValue
}
}
В этом примере:
increment.countValue автоматически вызывает
countValueChanged.updateOutput обновляет DOM без явной подписки на
изменения.Stimulus позволяет использовать несколько targets и value properties в одном контроллере, сохраняя реактивность. Например:
export default class extends Controller {
static targets = ["name", "greeting"]
static values = { username: String }
connect() {
this.updateGreeting()
}
usernameValueChanged() {
this.updateGreeting()
}
updateGreeting() {
this.greetingTarget.textContent = `Привет, ${this.usernameValue}`
}
}
Использование нескольких targets упрощает управление интерфейсом, а
value properties обеспечивают синхронизацию данных с DOM. Любое
изменение значения через this.usernameValue мгновенно
отражается на целевых элементах.
Stimulus оптимизирован для минимальной сложности:
targets и
value properties.Такой подход снижает объем кода и повышает читаемость приложения, сохраняя легковесность и скорость.
Stimulus корректно отслеживает динамически добавленные или удаленные
элементы. Если новый элемент содержит data-target,
контроллер автоматически его зарегистрирует:
const newDiv = document.createElement("div")
newDiv.dataset.counterTarget = "output"
document.body.appendChild(newDiv)
После добавления DOM Stimulus корректно свяжет newDiv с
контроллером, обеспечивая реактивность без дополнительной
инициализации.
Комбинация targets, value properties, и событий позволяет строить сложные реактивные интерфейсы с минимальной логикой:
Stimulus обеспечивает стабильную реактивность при изменениях DOM и значений, позволяя сохранять чистоту и структуру кода без громоздких подписок и библиотек.