StimulusJS с Turbolinks, должны ждать события "turbolinks:load" для запуска контроллеров StimulusJS

У меня есть довольно стандартное приложение Rails 5.2 (следует почти всем соглашениям), использующее пряжу и веб-упаковщик, с версией стимула 1.1.1 в моем package.json а также yarn.lock файл.

# package.json
{
  "name": "MY_APP_NAME",
  "private": true,
  "dependencies": {
    "@rails/webpacker": "^4.0.2",
    "coffeescript": "1.12.7",
    "stimulus": "^1.1.1"
  },
  "devDependencies": {
    "webpack-dev-server": "^3.2.1"
  }
}

Со страницы дискурса StimulusJS ( https://discourse.stimulusjs.org/t/stimulusjs-and-turbolinks/669), начиная со стимула 1.1, контроллеры стимулов выполняют методы подключения / инициализации после того, как DOM готов с турболинками.

Тем не менее, единственный способ, которым я мог заставить приведенный ниже контроллер работать должным образом, это добавить обработчик событий, чтобы дождаться, пока turbolinks:load Событие сработало.

Если это актуальная информация, я пытаюсь использовать плагин jQuery Select2 для создания пользовательского элемента выбора.

# app/javascript/packs/controllers/intake_customization_controller.js
import { Controller } from "stimulus";

export default class extends Controller {
  static targets = [ "userIds" ]

  initialize() {
    // Code will not execute without this event handler wrapping it...
    $(document).on("turbolinks:load", ()=> {
      $(this.userIdsTarget).select2()
    })
  }
}

HTML-форма:

<%= form_with model: @account, url: settings_intake_customization_path, method: :put, id: "settings-intake_customization-form", data: { controller: "intake-customization" } do |form| %>
  <%= form.collection_select :user_ids, current_account.users, :id, :name, { include_blank: false }, { multiple: true, data: { target: "intake-customization.userIds" } } %>
<% end %>

Я что-то упускаю при настройке контроллера стимула с турболинками?

С помощью turbolinks:load обработчик событий, я могу получить желаемую функциональность, но из того, что я прочитал на форуме Discourse, мне не нужно было использовать обработчик событий.

Возможно ли, что мое приложение "кэшировало" более старую версию Stimulus, хотя package.json говорит иначе?

1 ответ

Насколько я понимаю, Stimulus был разработан для работы с Turbolinks. Я был бы удивлен, если бы вам нужно было обернуть ваш код внутри обработчика событий для turbolinks:load, Вполне возможно, что вы можете использовать connect событие, а не initialize событие, потому что initialize Событие запускается при первом создании контроллера. connect событие срабатывает каждый раз, когда контроллер подключен к DOM.

Из документов для connection обратный вызов жизненного цикла, он заявляет:

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

  • его элемент присутствует в документе (т. е. потомок document.documentElement, элемент)
  • его идентификатор присутствует в атрибуте data-controller элемента

Когда контроллер подключается, Stimulus вызывает его метод connect().

Так как вы хотите манипулировать DOM с помощью jQuery Select2, connect жизненный цикл обратного вызова мне кажется более подходящим. Я сделаю еще несколько исследований, но я бы предположил, что initialize Событие запускается всякий раз, когда код для контроллера загружается в браузер. Если это так, то есть возможность initialize Событие запускается до того, как часть дерева DOM, которая использует ваш контроллер (и элемент DOM, который вы пытаетесь запросить), имеет возможность визуализации:

# app/javascript/packs/controllers/intake_customization_controller.js

import { Controller } from "stimulus";

export default class extends Controller {
  static targets = [ "userIds" ]

  connect() {
    $(this.userIdsTarget).select2()
  }
}

Я был в состоянии найти статью говорит, чтобы использовать connect скорее, чем turbolinks:load, Эта статья написана кем-то, кто опубликовал несколько учебных пособий по Stimulus, поэтому он выглядит довольно уважаемым. У меня проблемы с поиском чего-либо, что подробно описывает различия между initialize а также connect кроме этого initialize уволен один раз и connect срабатывает каждый раз, когда он подключен к DOM. Для того чтобы connect событие, которое будет запущено снова, необходимо disconnected событие произошло между

Другие вопросы по тегам