本文翻译自:Rails 4: how to use $(document).ready() with turbo-links
I ran into an issue in my Rails 4 app while trying to organize JS files "the rails way". 我试图组织JS文件“rails way”时,在我的Rails 4应用程序中遇到了一个问题。 They were previously scattered across different views. 他们以前分散在不同的观点中。 I organized them into separate files and compile them with the assets pipeline. 我将它们组织成单独的文件,并使用资产管道进行编译。 However, I just learned that jQuery's "ready" event doesn't fire on subsequent clicks when turbo-linking is turned on. 但是,我刚刚了解到,当打开turbo-linked时,jQuery的“就绪”事件不会触发后续点击。 The first time you load a page it works. 第一次加载页面时它可以工作。 But when you click a link, anything inside the ready( function($) {
won't get executed (because the page doesn't actually load again). Good explanation: here . 但是当你点击一个链接时, ready( function($) {
任何内容ready( function($) {
都不会被执行(因为页面实际上没有再次加载)。好的解释: 这里 。
So my question is: What is the right way to ensure that jQuery events work properly while turbo-links are on? 所以我的问题是:在启用turbo-links时,确保jQuery事件正常工作的正确方法是什么? Do you wrap the scripts in a Rails-specific listener? 您是否将脚本包装在特定于Rails的侦听器中? Or maybe rails has some magic that makes it unnecessary? 或者也许rails有一些魔力让它变得不必要? The docs are a bit vague on how this should work, especially with respect to loading multiple files via the manifest(s) like application.js. 文档对于它应该如何工作有点模糊,特别是关于通过像application.js这样的清单加载多个文件。
#1楼
参考:https://stackoom.com/question/1Gl4H/Rails-如何使用带有turbo-links的-document-ready
#2楼
Here's what I do... CoffeeScript: 这就是我做的...... CoffeeScript:
ready = ->
...your coffeescript goes here...
$(document).ready(ready)
$(document).on('page:load', ready)
last line listens for page load which is what turbo links will trigger. 最后一行侦听页面加载,这是turbo链接将触发的内容。
Edit ...adding Javascript version (per request): 编辑 ...添加Javascript版本(按请求):
var ready;
ready = function() {
...your javascript goes here...
};
$(document).ready(ready);
$(document).on('page:load', ready);
Edit 2 ...For Rails 5 (Turbolinks 5) page:load
becomes turbolinks:load
and will be even fired on initial load. 编辑2 ...对于Rails 5(Turbolinks 5) page:load
变为turbolinks:load
,甚至会在初始加载时触发。 So we can just do the following: 所以我们可以做到以下几点:
$(document).on('turbolinks:load', function() {
...your javascript goes here...
});
#3楼
Either use the 要么使用
$(document).on "page:load", attachRatingHandler
or use jQuery's .on function to achieve the same effect 或者使用jQuery的.on函数来实现相同的效果
$(document).on 'click', 'span.star', attachRatingHandler
see here for more details: http://srbiv.github.io/2013/04/06/rails-4-my-first-run-in-with-turbolinks.html 有关详细信息,请参阅此处: http : //srbiv.github.io/2013/04/06/rails-4-my-first-run-in-with-turbolinks.html
#4楼
I just learned of another option for solving this problem. 我刚学会了解决这个问题的另一种选择。 If you load the jquery-turbolinks
gem it will bind the Rails Turbolinks events to the document.ready
events so you can write your jQuery in the usual way. 如果加载jquery-turbolinks
gem,它会将Rails Turbolinks事件绑定到document.ready
事件,这样你就可以用通常的方式编写jQuery。 You just add jquery.turbolinks
right after jquery
in the js manifest file (by default: application.js
). 你只需要添加jquery.turbolinks
之后jquery
在js清单文件(默认: application.js
)。
#5楼
NOTE: See @SDP's answer for a clean, built-in solution 注意:请参阅@ SDP的答案,了解干净的内置解决方案
I fixed it as follows: 我把它固定如下:
make sure you include application.js before the other app dependent js files get included by changing the include order as follows: 通过更改include顺序,确保在包含其他应用程序相关js文件之前包含application.js,如下所示:
// in application.js - make sure `require_self` comes before `require_tree .`
//= require_self
//= require_tree .
Define a global function that handles the binding in application.js
定义一个处理application.js
绑定的全局函数
// application.js
window.onLoad = function(callback) {
// binds ready event and turbolink page:load event
$(document).ready(callback);
$(document).on('page:load',callback);
};
Now you can bind stuff like: 现在你可以绑定像:
// in coffee script:
onLoad ->
$('a.clickable').click =>
alert('link clicked!');
// equivalent in javascript:
onLoad(function() {
$('a.clickable').click(function() {
alert('link clicked');
});
#6楼
Recently I found the most clean and easy to understand way of dealing with it: 最近我找到了最简洁易懂的处理方式:
$(document).on 'ready page:load', ->
# Actions to do
OR 要么
$(document).on('ready page:load', function () {
// Actions to do
});
EDIT 编辑
If you have delegated events bound to the document
, make sure you attach them outside of the ready
function, otherwise they will get rebound on every page:load
event (causing the same functions to be run multiple times). 如果您已将委托事件绑定到document
,请确保将它们附加到ready
函数之外,否则它们将在每个page:load
上反弹page:load
event(导致相同的函数多次运行)。 For example, if you have any calls like this: 例如,如果您有任何这样的调用:
$(document).on 'ready page:load', ->
...
$(document).on 'click', '.button', ->
...
...
Take them out of the ready
function, like this: 将它们从ready
功能中取出,如下所示:
$(document).on 'ready page:load', ->
...
...
$(document).on 'click', '.button', ->
...
Delegated events bound to the document
do not need to be bound on the ready
event. 绑定到document
委托事件不需要绑定到ready
事件。