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
событие произошло между