Rails 4: как использовать $(document).ready() с турбо-ссылками
Я столкнулся с проблемой в своем Rails 4 при попытке организовать JS файлы "путь рельсов". Раньше они были разбросаны по разным взглядам. Я организовал их в отдельные файлы и скомпилировал их с помощью конвейера активов. Тем не менее, я только что узнал, что событие jQuery "ready" не срабатывает при последующих нажатиях, когда включено турбосвязывание. При первой загрузке страницы она работает. Но когда вы нажимаете ссылку, что-либо внутри ready( function($) {
не будет выполнено (потому что страница на самом деле не загружается снова). Хорошее объяснение: здесь.
Итак, мой вопрос: какой правильный способ обеспечить правильное функционирование jQuery-событий во время включения турбо-ссылок? Вы завершаете скрипты в Rails-специфическом слушателе? Или, может быть, у рельсов есть какая-то магия, которая делает это ненужным? Документы немного расплывчаты в отношении того, как это должно работать, особенно в отношении загрузки нескольких файлов через манифест (ы), например application.js.
Ответы
Ответ 1
Я только что узнал о другом варианте решения этой проблемы. Если вы загрузите драгоценный камень jquery-turbolinks
, он привяжет события Rails Turbolinks к событиям document.ready
, чтобы вы могли написать свой jQuery обычным способом. Вы просто добавляете jquery.turbolinks
сразу после jquery
в файл манифеста js (по умолчанию: application.js
).
Ответ 2
Вот что я делаю...
CoffeeScript:
ready = ->
...your coffeescript goes here...
$(document).ready(ready)
$(document).on('page:load', ready)
Последняя строка прослушивает загрузку страницы, что вызывает турбо-ссылки.
Изменить... добавление версии Javascript (для каждого запроса):
var ready;
ready = function() {
...your javascript goes here...
};
$(document).ready(ready);
$(document).on('page:load', ready);
Изменить 2... Для Rails 5 (Turbolinks 5) page:load
становится turbolinks:load
и будет даже запущен при начальной загрузке. Поэтому мы можем просто сделать следующее:
$(document).on('turbolinks:load', function() {
...your javascript goes here...
});
Ответ 3
Недавно я нашел самый чистый и понятный способ борьбы с ним:
$(document).on 'ready page:load', ->
# Actions to do
ИЛИ
$(document).on('ready page:load', function () {
// Actions to do
});
ИЗМЕНИТЬ
Если у вас делегированные события связаны с document
, убедитесь, что вы прикрепляете их вне функции ready
, иначе они будут отскакивать каждый page:load
событие (заставляя одни и те же функции запускаться несколько раз). Например, если у вас есть такие вызовы, как:
$(document).on 'ready page:load', ->
...
$(document).on 'click', '.button', ->
...
...
Выньте их из функции ready
, например:
$(document).on 'ready page:load', ->
...
...
$(document).on 'click', '.button', ->
...
Делегированные события, связанные с document
, не должны быть связаны с событием ready
.
Ответ 4
Обнаружено это в документации Rails 4, аналогично решению DemoZluk, но немного короче:
$(document).on 'page:change', ->
# Actions to do
ИЛИ
$(document).on('page:change', function () {
// Actions to do
});
Если у вас есть внешние скрипты, вызывающие $(document).ready()
, или если вас не беспокоит переписывание всего вашего существующего JavaScript, то этот камень позволяет вам использовать $(document).ready()
с TurboLinks: https://github.com/kossnocorp/jquery.turbolinks
Ответ 5
В соответствии с новыми направляющими rails правильный способ заключается в следующем:
$(document).on('turbolinks:load', function() {
console.log('(document).turbolinks:load')
});
или, в coffeescript:
$(document).on "turbolinks:load", ->
alert "page has loaded!"
Не слушайте событие $(document).ready
, и только одно событие будет запущено. Никаких сюрпризов, нет необходимости использовать драгоценный камень jquery.turbolinks.
Это работает с рельсами 4.2 и выше, а не только с рельсами 5.
Ответ 6
ПРИМЕЧАНИЕ. См. ответ @SDP для чистого встроенного решения
Я зафиксировал его следующим образом:
убедитесь, что вы включили application.js, прежде чем другие зависимые от приложения js файлы будут включены, изменив порядок включения следующим образом:
// in application.js - make sure `require_self` comes before `require_tree .`
//= require_self
//= require_tree .
Определите глобальную функцию, которая обрабатывает привязку в application.js
// application.js
window.onLoad = function(callback) {
// binds ready event and turbolink page:load event
$(document).ready(callback);
$(document).on('page:load',callback);
};
Теперь вы можете связать такие вещи, как:
// in coffee script:
onLoad ->
$('a.clickable').click =>
alert('link clicked!');
// equivalent in javascript:
onLoad(function() {
$('a.clickable').click(function() {
alert('link clicked');
});
Ответ 7
Ничего из этого не работает для меня, я решил это, не используя jQuery $(document).ready, но вместо этого используйте addEventListener.
document.addEventListener("turbolinks:load", function() {
// do something
});
Ответ 8
$(document).on 'ready turbolinks:load', ->
console.log '(document).turbolinks:load'
Ответ 9
Вы должны использовать:
document.addEventListener("turbolinks:load", function() {
// your code here
})
из турболинкского документа.
Ответ 10
Либо используйте
$(document).on "page:load", attachRatingHandler
или использовать функцию jQuery.on для достижения того же эффекта
$(document).on 'click', 'span.star', attachRatingHandler
см. здесь для более подробной информации: http://srbiv.github.io/2013/04/06/rails-4-my-first-run-in-with-turbolinks.html
Ответ 11
Вместо использования переменной для сохранения "готовой" функции и привязки ее к событиям вы можете запускать событие ready
при срабатывании page:load
.
$(document).on('page:load', function() {
$(document).trigger('ready');
});
Ответ 12
Вот то, что я сделал для обеспечения того, что вещи не выполняются дважды:
$(document).on("page:change", function() {
// ... init things, just do not bind events ...
$(document).off("page:change");
});
Я нахожу использование жемчужины jquery-turbolinks
или комбинирование $(document).ready
и $(document).on("page:load")
или используя $(document).on("page:change")
самостоятельно ведет себя неожиданно - особенно если вы находитесь в разработке.
Ответ 13
Я нашел следующую статью которая отлично поработала для меня и подробно описывает следующее:
var load_this_javascript = function() {
// do some things
}
$(document).ready(load_this_javascript)
$(window).bind('page:change', load_this_javascript)
Ответ 14
Я решил, что оставлю это здесь для тех, кто обновляется до Turbolinks 5: самый простой способ исправить ваш код - перейти от:
var ready;
ready = function() {
// Your JS here
}
$(document).ready(ready);
$(document).on('page:load', ready)
в
var ready;
ready = function() {
// Your JS here
}
$(document).on('turbolinks:load', ready);
Ссылка: https://github.com/turbolinks/turbolinks/issues/9#issuecomment-184717346
Ответ 15
$(document).ready(ready)
$(document).on('turbolinks:load', ready)
Ответ 16
Я обычно делаю следующие для моих рельсов 4 проекта:
В application.js
function onInit(callback){
$(document).ready(callback);
$(document).on('page:load', callback);
}
Затем в остальных.js файлах вместо использования $(function(){})
я вызываю onInit(function(){})
Ответ 17
<%= link_to 'Edit', edit_article_path(article), 'data-no-turbolink' => true %>
Может быть, вы можете использовать это, чтобы использовать "готово", это точно так же, как закрыть турболинк.
Ответ 18
Сначала установите jquery-turbolinks
gem. И затем, не забудьте переместить ваши включенные файлы Javascript из конца тела вашего application.html.erb
в его <head>
.
Как описанный здесь, если вы поместили ссылку javascript приложения в нижний колонтитул для оптимизации скорости, вам нужно будет переместить ее в чтобы он загружался до содержимого в теге. Это решение сработало для меня.
Ответ 19
Протестировано так много решений, наконец, дошло до этого.
Этот код не обязательно дважды вызывается.
var has_loaded=false;
var ready = function() {
if(!has_loaded){
has_loaded=true;
// YOURJS here
}
}
$(document).ready(ready);
$(document).bind('page:change', ready);
Ответ 20
Я обнаружил, что мои функции удвоились при использовании функции для ready
и turbolinks:load
, поэтому я использовал
var ready = function() {
// you code goes here
}
if (Turbolinks.supported == false) {
$(document).on('ready', ready);
};
if (Turbolinks.supported == true) {
$(document).on('turbolinks:load', ready);
};
Таким образом, ваши функции не удваиваются, если поддерживаются turbolinks!