jQuery Rails 4:如何将 $(document).ready() 与 turbo-links 一起使用

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/18770517/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-26 22:28:27  来源:igfitidea点击:

Rails 4: how to use $(document).ready() with turbo-links

javascriptjqueryruby-on-rails-4asset-pipelineturbolinks

提问by emersonthis

I ran into an issue in my Rails 4 app while trying to organize JS files "the rails way". 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. 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.

在尝试以“rails 方式”组织 JS 文件时,我在 Rails 4 应用程序中遇到了一个问题。它们以前分散在不同的视图中。我将它们组织成单独的文件并使用资产管道编译它们。但是,我刚刚了解到,当打开 turbo-linking 时,jQuery 的“ready”事件不会在后续点击时触发。第一次加载页面时,它可以工作。但是当你点击一个链接时,里面的任何东西ready( function($) {都不会被执行(因为页面实际上不会再次加载)。很好的解释:这里

So my question is: What is the right way to ensure that jQuery events work properly while turbo-links are on? Do you wrap the scripts in a Rails-specific listener? Or maybe rails has some magic that makes it unnecessary? 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.

所以我的问题是:确保 jQuery 事件在 turbo-links 打开时正常工作的正确方法是什么?您是否将脚本包装在特定于 Rails 的侦听器中?或者 Rails 有一些魔法让它变得不必要?文档对这应该如何工作有点模糊,特别是在通过清单加载多个文件(如 application.js)方面。

采纳答案by emersonthis

I just learned of another option for solving this problem. If you load the jquery-turbolinksgemit will bind the Rails Turbolinks events to the document.readyevents so you can write your jQuery in the usual way. You just add jquery.turbolinksright after jqueryin the js manifest file (by default: application.js).

我刚刚了解到解决此问题的另一种选择。如果加载jquery-turbolinks宝石它将绑定Rails的Turbolinks事件的document.ready事件,这样你就可以用通常的方式写你的jQuery。您只需在 js 清单文件jquery.turbolinks之后添加jquery(默认情况下:)application.js

回答by Meltemi

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.

最后一行侦听页面加载,这是涡轮链接将触发的。

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:loadbecomes turbolinks:loadand will be even fired on initial load. So we can just do the following:

编辑 2...对于 Rails 5 (Turbolinks 5)page:load成为turbolinks:load并且甚至会在初始加载时被触发。所以我们可以做以下事情:

$(document).on('turbolinks:load', function() {

  ...your javascript goes here...

});

回答by Artyom Tsoy

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 eventsbound to the document, make sure you attach them outside of the readyfunction, otherwise they will get rebound on every page:loadevent (causing the same functions to be run multiple times). For example, if you have any calls like this:

编辑
如果您已委托绑定到 的事件document,请确保将它们附加到ready函数之外,否则它们将在每个page:load事件上反弹(导致多次运行相同的函数)。例如,如果您有任何这样的电话:

$(document).on 'ready page:load', ->
  ...
  $(document).on 'click', '.button', ->
    ...
  ...

Take them out of the readyfunction, like this:

将它们从ready函数中取出,如下所示:

$(document).on 'ready page:load', ->
  ...
  ...

$(document).on 'click', '.button', ->
  ...

Delegated events bound to the documentdo not need to be bound on the readyevent.

绑定到 的委托事件document不需要绑定到ready事件上。

回答by migu

Found this in the Rails 4 documentation, similar to DemoZluk's solution but slightly shorter:

Rails 4 文档中找到了这个,类似于 DemoZluk 的解决方案,但略短:

$(document).on 'page:change', ->
  # Actions to do

OR

或者

$(document).on('page:change', function () {
  // Actions to do
});

If you have external scripts that call $(document).ready()or if you can't be bothered rewriting all your existing JavaScript, then this gem allows you to keep using $(document).ready()with TurboLinks: https://github.com/kossnocorp/jquery.turbolinks

如果您有外部脚本调用$(document).ready()或者如果您不想重写所有现有的 JavaScript,那么这个 gem 允许您继续使用$(document).ready()TurboLinks:https: //github.com/kossnocorp/jquery.turbolinks

回答by vedant

As per the new rails guides, the correct way is to do the following:

根据新的导轨指南,正确的方法是执行以下操作:

$(document).on('turbolinks:load', function() {
   console.log('(document).turbolinks:load')
});

or, in coffeescript:

或者,在咖啡脚本中:

$(document).on "turbolinks:load", ->
alert "page has loaded!"

Do not listen to the event $(document).readyand only one event will be fired. No surprises, no need to use the jquery.turbolinksgem.

不监听事件$(document).ready,只会触发一个事件。毫无意外,无需使用jquery.turbolinksgem。

This works with rails 4.2 and above, not only rails 5.

这适用于 rails 4.2 及更高版本,而不仅仅是 rails 5。

回答by sled

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:

通过如下更改包含顺序,确保在包含其他应用程序相关 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');
});

回答by RockL

None of the above works for me, I solved this by not using jQuery's $(document).ready, but use addEventListener instead.

以上都不适合我,我通过不使用 jQuery 的 $(document).ready 解决了这个问题,而是使用 addEventListener 。

document.addEventListener("turbolinks:load", function() {
  // do something
});

回答by Sukeerthi Adiga

$(document).on 'ready turbolinks:load', ->
  console.log '(document).turbolinks:load'

回答by Gian Franco Fioriello

You have to use:

你必须使用:

document.addEventListener("turbolinks:load", function() {
  // your code here
})

from turbolinks doc.

来自 turbolinks 文档

回答by derekyau

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