В конечном счете, с выходами в Stimulus можно создавать более модульные и удобные в сопровождении приложения. Розетки позволяют контроллерам общаться и работать вместе более эффективно и организованно, снижая риск ошибок и упрощая обновление или изменение кода в будущем. Кроме того, разбивая сложную логику на более мелкие, более целенаправленные части, розетки могут помочь улучшить качество и читабельность кода.

Таким образом, розетки являются важной функцией Stimulus, которая может значительно улучшить способ взаимодействия и связи контроллеров друг с другом. Они позволяют разбить сложную функциональность на более мелкие, более управляемые части, обеспечивая большую модульность, гибкость и удобство сопровождения в веб-приложениях.

Описание розеток

Розетки — это функция Stimulus, которая обеспечивает более эффективную и действенную связь между различными контроллерами. Концептуально они очень похожи на «цели» или «значения», с той разницей, что выход предоставляет доступ к экземпляру контроллера и, следовательно, к его свойствам, методам и событиям.

Чтобы использовать выход, он определяется в коде HTML с помощью простого селектора CSS. В коде JavaScript контроллера выход можно использовать для доступа к свойствам, методам и событиям целевого контроллера.

Давайте возьмем пример документации Stimulus, чтобы проиллюстрировать использование розеток. Предположим, у нас есть контроллер для списка задач и еще один для формы задачи. Чтобы связать два контроллера вместе, можно определить выход в контроллере результатов поиска и извлечения:

<div data-controller="search" data-search-result-outlet="#result">…</div>

<div id="result" data-controller="result">…</div>

Здесь контроллер поиска извлекает экземпляр контроллера результатов. Если мы войдем внутрь контроллера, мы сможем легко вызвать его.

// search_controller.js

export default class extends Controller {
  static outlets = [ "result" ]
  connect () {
    this.resultOutlet.method();
  }
}

Конечно, можно получить несколько разных контроллеров с помощью другого селектора CSS, например:

<div data-controller="search" data-search-result-outlet=".result">…</div>
<div id="results">
 <div class="result" data-controller="result">…</div>
 <div class="result" data-controller="result">…</div>
</div>

И называть их так же, как цели.

// search_controller.js
export default class extends Controller {
  static outlets = [ "result" ]
  connect () {
    this.resultOutlets.forEach(result => ...)
  }
}

Практические примеры

Давайте представим типичный процесс адаптации пользователя с индикатором выполнения, подобным тому, который предоставляется Bootstrap для упрощения. У нас есть следующий HTML-код:

<div class="progress" id="progress" data-controller="progress-bar">
  <div class="progress-bar" role="progressbar" 
       style="width: 0%" aria-valuenow="0" aria-valuemin="0" 
       aria-valuemax="100"
       data-search-target="progress-bar">
  </div>
</div>
<turbo-frame id="onboardingStep"%></turbo-frame>

Ассоциированный контроллер

// progress_bar_controller.js
export default class extends Controller {
  static outlets = [ "result" ]
  nextStep () {
    const width = this.progressBarTarget.style.width
    this.progressBarTarget.style.width = parseInt(width) + 10 + "%";
  }
}

Затем мы можем думать о любом действии, таком как щелчок по переключателю, отправка формы, выбор варианта, таймер или что-то еще. Достаточно получить доступ к контроллеру с помощью такого действия:

<div data-controller="other" data-search-progress-bar-outlet="#progress">
  <button data-action="click->other#nextStep"></button>
</div>

И ассоциированный контроллер

// other_controller.js
export default class extends Controller {
  static target = [ "progressBar" ]
  nextStep () {
    this.progressBarOutlet.nextStep();
  }
}

Что довольно удивительно, так это то, что мы можем перезагрузить Turbo Frame, но при этом по-прежнему можно получить доступ к контроллеру индикатора выполнения. Это позволяет нам перезагружать меньшую часть страницы в бэкенде и дает реальное ощущение реактивности.

Заключение

С помощью розеток можно создавать более сложные архитектуры, используя компоненты, взаимодействующие друг с другом. Например, мы могли бы использовать связанные контроллеры для открытия модальных окон или холстов, а не использовать один контроллер для управления всей страницей. Это позволило бы нам поддерживать динамический и реактивный эффект страницы без необходимости обращаться со слишком тяжелым контроллером.

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

Таким образом, добавление розеток в Stimulus открывает множество возможностей для создания сложных и модульных архитектур.