Stimulus строится на принципах минимализма и декларативного подхода к
управлению поведением элементов DOM. Каждый контроллер представляет
собой отдельный блок логики, связанный с определённым элементом страницы
через атрибут data-controller. Взаимодействие между
контроллерами осуществляется через события, значения и
действия, что позволяет строить модульную и легко
поддерживаемую архитектуру.
Контроллеры Stimulus используют стандартную модель событий DOM для
взаимодействия. Внутри одного контроллера события обрабатываются через
методы, объявленные с помощью data-action. Например, кнопка
может инициировать событие click, которое вызывает метод
контроллера:
<button data-action="click->menu#toggle">Меню</button>
export default class extends Controller {
toggle() {
this.element.classList.toggle("open");
const event = new CustomEvent("menu:toggled", { bubbles: true });
this.element.dispatchEvent(event);
}
}
Событие menu:toggled можно поймать в другом контроллере,
назначив слушатель на общий родительский элемент:
export default class extends Controller {
connect() {
this.element.addEventListener("menu:toggled", this.menuToggled.bind(this));
}
menuToggled(event) {
console.log("Меню было открыто или закрыто");
}
}
Ключевой момент: использование
CustomEvent с bubbles: true обеспечивает
проброс события вверх по DOM, что делает возможным коммуникацию между
разными контроллерами без жёсткой зависимости.
Stimulus предоставляет механизм значений для
управления состоянием и передачи данных между контроллерами через
атрибуты DOM. Значения определяются в контроллере через
static values:
export default class extends Controller {
static values = { count: Number }
increment() {
this.countValue++
this.dispatch("changed", { detail: { count: this.countValue } })
}
}
В другом контроллере можно подписаться на событие
changed:
export default class extends Controller {
connect() {
this.element.addEventListener("counter:changed", this.updateCounter.bind(this))
}
updateCounter(event) {
const newCount = event.detail.count
console.log("Новое значение счётчика:", newCount)
}
}
Использование значений облегчает синхронизацию состояния между контроллерами без прямого вызова методов друг друга.
Механизм действий позволяет контроллерам реагировать на события DOM,
такие как click, input, submit.
Атрибут data-action связывает событие с методом
контроллера. Он поддерживает множественные обработчики и даже передачу
аргументов:
<input type="text" data-action="input->search#update value->search#filter" />
Контроллер search может обрабатывать несколько событий
одновременно, управляя поведением одного элемента:
export default class extends Controller {
update(event) {
this.query = event.target.value
}
filter() {
console.log("Фильтруем по:", this.query)
}
}
Target для взаимодействия между контроллерамиTargets позволяют контроллеру оперировать конкретными элементами
внутри своего DOM-контейнера. При необходимости передачи данных между
контроллерами, один контроллер может воздействовать на элементы другого
через события или dispatch:
<div data-controller="modal">
<div data-modal-target="content"></div>
</div>
<div data-controller="trigger">
<button data-action="click->trigger#openModal">Открыть модальное окно</button>
</div>
// trigger_controller.js
export default class extends Controller {
openModal() {
this.element.dispatchEvent(new CustomEvent("modal:open", { bubbles: true }))
}
}
// modal_controller.js
export default class extends Controller {
static targets = ["content"]
connect() {
this.element.addEventListener("modal:open", () => {
this.contentTarget.textContent = "Модальное окно открыто"
this.element.classList.add("active")
})
}
}
data-* атрибутыStimulus позволяет строить взаимодействие между контроллерами полностью декларативно. Все связи происходят через HTML-атрибуты:
data-controller — назначение контроллера элементу.data-action — обработка событий DOM.data-target — выделение элементов внутри
контроллера.data-*-value — определение и управление
значениями.Такой подход снижает связность компонентов и делает код более модульным и читаемым.
Элемент может содержать несколько контроллеров, что позволяет разрабатывать сложные интерфейсы с независимыми слоями поведения:
<div data-controller="tabs dropdown" data-tabs-value="1" data-dropdown-value="false">
<button data-action="click->tabs#select click->dropdown#toggle">Кнопка</button>
</div>
Каждый контроллер остаётся автономным, обрабатывает свои события и значения, но при необходимости может обмениваться данными через события.
bubbles: true для передачи данных между разными
уровнями DOM.Stimulus предлагает минималистичный, но мощный подход к организации взаимодействия между контроллерами, делая код декларативным, модульным и легко расширяемым.