Stimulus — это легковесный JavaScript-фреймворк, предназначенный для добавления динамического поведения на страницы без полного перехода на SPA. Его основная идея заключается в минимальном вмешательстве в структуру HTML и использовании контроллеров для управления поведением элементов. Контроллеры связывают HTML-атрибуты с JavaScript-кодом, что позволяет создавать интерактивные компоненты, сохраняя при этом семантику и структуру DOM.
Контроллеры Stimulus наследуются от базового класса
Controller и управляются через
data-атрибуты, например:
<div data-controller="example">
<button data-action="click->example#greet">Нажми меня</button>
</div>
В этом примере клик на кнопке вызывает метод greet
контроллера example. Такая привязка позволяет избежать
написания громоздких обработчиков через querySelector и
addEventListener.
Stimulus использует три ключевых типа атрибутов:
Пример:
<div data-controller="counter">
<span data-counter-target="output">0</span>
<button data-action="click->counter#increment">+</button>
</div>
Контроллер counter может выглядеть так:
import { Controller } from "@hotwired/stimulus"
export default class extends Controller {
static targets = ["output"]
increment() {
this.outputTarget.textContent = parseInt(this.outputTarget.textContent) + 1
}
}
Использование targets делает код чище и устраняет
необходимость постоянно искать элементы в DOM.
Web Components предоставляют стандартизированный способ создания кастомных HTML-элементов с инкапсулированным поведением и стилями. Stimulus дополняет Web Components, обеспечивая легкую интеграцию логики без нарушения принципов инкапсуляции. Взаимодействие между Stimulus и Web Components строится на привязке контроллеров к элементам внутри Shadow DOM или к самим кастомным элементам.
class MyWidget extends HTMLElement {
constructor() {
super()
this.attachShadow({ mode: 'open' })
this.shadowRoot.innerHTML = `<button id="actionBtn">Click me</button>`
}
}
customElements.define('my-widget', MyWidget)
Stimulus-контроллер:
import { Controller } from "@hotwired/stimulus"
export default class extends Controller {
connect() {
this.element.shadowRoot.querySelector('#actionBtn')
.addEventListener('click', () => console.log('Clicked'))
}
}
Такой подход позволяет управлять поведением Web Component через Stimulus, сохраняя изоляцию Shadow DOM.
Stimulus управляет жизненным циклом контроллеров через стандартные методы:
connect() — вызывается при привязке контроллера к
DOM.disconnect() — вызывается при удалении элемента из
DOM.initialize() — вызывается перед connect(),
используется для начальной настройки.Правильное использование этих методов позволяет управлять событиями и ресурсами, предотвращая утечки памяти при динамическом обновлении страниц.
Stimulus поддерживает value-attributes, которые позволяют хранить состояние контроллера прямо в HTML. Например:
<div data-controller="count" data-count-value="5">
<span data-count-target="output"></span>
</div>
Контроллер:
import { Controller } from "@hotwired/stimulus"
export default class extends Controller {
static targets = ["output"]
static values = { count: Number }
connect() {
this.outputTarget.textContent = this.countValue
}
}
Использование values делает код декларативным и упрощает
синхронизацию состояния между DOM и контроллером.
Stimulus легко масштабируется за счет множественных контроллеров на одной странице. Контроллеры могут быть независимыми или взаимодействовать через события CustomEvent:
this.element.dispatchEvent(new CustomEvent('update', { detail: { value: 10 }, bubbles: true }))
Другой контроллер может слушать событие update и
реагировать соответствующим образом. Такой подход позволяет строить
сложные интерфейсы без жесткой связки между компонентами.
Stimulus идеально работает с Webpack, Vite и другими сборщиками
модулей. Контроллеры могут быть организованы в директории
controllers, автоматически подключаться через
index.js:
import { Application } from "@hotwired/stimulus"
import ExampleController from "./example_controller"
const application = Application.start()
application.register("example", ExampleController)
Это позволяет создавать чистую, модульную структуру проекта, где каждый контроллер отвечает за конкретную часть интерфейса.
Работа с Shadow DOM требует явного обращения к
shadowRoot. Stimulus не ломает инкапсуляцию компонентов, но
для управления элементами внутри Shadow DOM необходимо использовать
querySelector внутри shadowRoot, как показано
выше. При этом контроллеры могут быть привязаны как к самим кастомным
элементам, так и к их внутренней структуре, если это необходимо.
Stimulus обеспечивает простой и декларативный способ управления динамическим поведением страниц, гармонично сочетаясь с Web Components. Контроллеры, targets и values позволяют строить модульные, легко поддерживаемые интерфейсы, а интеграция с Shadow DOM и кастомными элементами делает его удобным инструментом в современных фронтенд-проектах.