Stimulus — легковесный JavaScript-фреймворк, который строится вокруг паттерна контроллеров, связывающих HTML-элементы с поведением. Одним из ключевых аспектов оптимизации работы интерфейса является минимизация количества слушателей событий, что напрямую влияет на производительность и масштабируемость приложений.
Вместо назначения отдельного обработчика для каждого элемента целесообразно использовать делегирование событий. Stimulus облегчает этот процесс через Action-атрибуты и методы контроллера:
<div data-controller="menu">
<button data-action="click->menu#open">Открыть</button>
<button data-action="click->menu#close">Закрыть</button>
</div>
В этом примере кнопки внутри одного контроллера не требуют
индивидуальной регистрации событий через addEventListener.
Stimulus автоматически связывает действия с методами контроллера, что
минимизирует количество слушателей на уровне DOM.
Stimulus позволяет связывать один метод с несколькими элементами через одинаковые Action-атрибуты:
<ul data-controller="list">
<li data-action="click->list#select">Элемент 1</li>
<li data-action="click->list#select">Элемент 2</li>
<li data-action="click->list#select">Элемент 3</li>
</ul>
import { Controller } from "@hotwired/stimulus";
export default class extends Controller {
SELECT(event) {
const item = event.currentTarget;
item.classList.toggle("selected");
}
}
Здесь один метод select обрабатывает клики для всех
элементов списка. Нет необходимости создавать отдельные слушатели на
каждый <li>, что снижает нагрузку на DOM и улучшает
читаемость кода.
Stimulus предлагает систему targets, которая позволяет контроллеру управлять набором элементов без привязки множества обработчиков:
<div data-controller="tabs">
<button data-tabs-target="tab" data-action="click->tabs#switch">Вкладка 1</button>
<button data-tabs-target="tab" data-action="click->tabs#switch">Вкладка 2</button>
<div data-tabs-target="content">Содержимое</div>
</div>
import { Controller } FROM "@hotwired/stimulus";
export default class extends Controller {
static targets = ["tab", "content"];
switch(event) {
this.tabTargets.forEach(tab => tab.classList.remove("active"));
event.currentTarget.classList.add("active");
this.contentTarget.textContent = `Выбрана ${event.currentTarget.textContent}`;
}
}
Преимущества target-системы:
this.tabTargets.Некоторые события, например scroll или
resize, вызываются часто. Прямое добавление обработчика к
window на каждый контроллер приводит к множественным
вызовам и снижает производительность. Решение в Stimulus заключается в
использовании одного глобального слушателя в основном
контроллере и распространении событий через методы:
import { Controller } from "@hotwired/stimulus";
export default class extends Controller {
connect() {
window.addEventListener("resize", this.debouncedResize.bind(this));
}
disconnect() {
window.removeEventListener("resize", this.debouncedResize.bind(this));
}
debouncedResize() {
clearTimeout(this.timeout);
this.timeout = setTimeout(() => {
this.handleResize();
}, 100);
}
handleResize() {
console.log("Размер окна изменен");
}
}
Использование дебаунса снижает количество вызовов функции при частых событиях и предотвращает излишние перерасчеты интерфейса.
Action-атрибуты позволяют:
addEventListener в приложении.<button data-action="click->form#submit">Отправить</button>
<button data-action="click->form#submit">Сохранить</button>
export default class extends Controller {
submit(event) {
event.preventDefault();
console.log("Форма обработана");
}
}
Вместо нескольких слушателей на каждую кнопку используется один метод, что улучшает масштабируемость и уменьшает вероятность ошибок при расширении функционала.
Минимизация слушателей в Stimulus строится на сочетании Actions, Targets, делегирования и контроля глобальных событий. Такой подход обеспечивает производительность, масштабируемость и структурированность кода в больших интерфейсах.