Я перенес свое приложение на Ruby on Rails 5 (v5.2.2) и пытаюсь использовать Turbolinks 5 (v5.2.0).
В моем приложении есть файлы просмотра, которые включают элементы <script>, и я хотел бы, чтобы они правильно работали с Turbolinks (чей документация указывает на избегайте элементов сценария и вместо этого используйте событие turbolinks:load). Что я должен сделать?
То есть, например, у меня есть:
# app/views/.../_partial_template.html.erb
<script type = "text/javascript">
$(document).ready(function () {
$.ajax({...})
});
// Note: I tried to use $(document).on('turbolinks:load', function() {...});
// and it seems that the JS code runs twice (or more) on every page load.
// I also tried to use <script type = "text/javascript" data-turbolinks-eval = "false">...</script>
// without success.
</script>
Как мне реорганизовать приведенный выше код, чтобы он правильно работал с Turbolinks?
Бонус:
Turbolinks документация говорит: Вы можете использовать встроенные сценарии тела для настройки состояния JavaScript для каждой страницы или начальной загрузки моделей на стороне клиента.. Что они имеют в виду под «постраничным состоянием JavaScript» и «загрузочными клиентскими моделями»?



![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


Если ваши встроенные скрипты включены в нижнюю часть <body> (или если они не сразу манипулируют DOM), вы можете удалить свой код из функции $(document).ready… и заставить их работать должным образом.
Встроенные сценарии, как правило, не рекомендуются, потому что традиционно они указывают, что код будет выполняться только на той странице, на которой он включен, и что любые прослушиватели событий будут автоматически уничтожены, когда пользователь уйдет. Однако в приложениях Turbolinks это не так. Если вы добавите прослушиватель событий во встроенный скрипт (и не удалите его), он продолжит прослушивание и запуск при последующих загрузках страницы. Как вы обнаружили, настроив прослушиватель событий turbolinks:load таким образом, обработчик срабатывал при загрузке последующих страниц, а при повторном посещении первой страницы прослушиватель событий добавлялся снова, что приводило к дублированию вызовов.
Что касается настройки «состояния JavaScript для каждой страницы» и «моделей начальной загрузки на стороне клиента», скажем, у вас есть страница календаря, которую вы хотите улучшить с помощью JavaScript. У вас может быть Calendar класс JavaScript, который обрабатывает это, поэтому вы можете включить следующее, чтобы загрузить его с помощью JSON:
<script>new Calendar(<%= @calendar.to_json %>)</script>
(учитывая, что любые добавленные прослушиватели событий, настроенные в классе Calender, вероятно, должны быть уничтожены в какой-то момент, например, turbolinks:before-cache).
Это демонстрирует идею, но в этом случае лучшим подходом может быть установка системы, которая ищет элементы календаря и в DOM, а затем создает их экземпляры. Например:
<div data-component = "calendar" data-props = "<%= @calendar.to_json %>">…</div>
затем в вашем JavaScript (входит в комплект приложения):
;(function () {
var calendar
$(document).on('turbolinks:load', function () {
var $el = $('[data-component=calendar]')
if ($el.length) calendar = new Calender($el.data('props'))
})
$(document).on('turbolinks:before-cache', function () {
if (calendar) {
calendar.destroy() // to teardown any event listeners etc
calender = null
}
})
})()
Этот подход можно обобщить, и здесь я рассмотрел одну реализацию: https://stackoverflow.com/a/44057187/783009.
Надеюсь, это поможет!