Rails 5:如何在Turbo-links中使用$(document).ready()函数

95

Turbolinks防止除初始加载外所有页面访问触发普通的$(document).ready()事件,如在这里这里所讨论的。然而,链接答案中的解决方案都不适用于Rails 5。如何像之前的版本一样在每个页面访问时运行代码?

9个回答

183

你需要挂接到 Turbolinks 每次访问页面时触发的事件,而不是监听 ready 事件。

不幸的是,Turbolinks 5(Rails 5 中出现的版本)已被重写,并且与早期版本中使用的事件名称不同,导致之前提到的答案失败。现在有效的方法是监听 turbolinks:load 事件,如下所示:

$( document ).on('turbolinks:load', function() {
  console.log("It works on each visit!")
})

6
是的。在这里也有解释:http://guides.rubyonrails.org/working_with_javascript_in_rails.html#turbolinks。请查看5.2页面更改事件。 - Indika K
3
Turbolinks:load 在本地环境下可以触发,但在 Heroku 上却不行。我在编译后的 js 资源中看到了我的自定义 JavaScript 代码,但事件没有被触发。 - psparrow
3
虽然 Rail 文档上说要使用 on('turbolinks:load'),但我会使用 on('ready turbolinks:load'),否则在某些页面上会遇到一些问题。 - Cyril Duchon-Doris
1
嗨 Cyril,我遇到了同样的问题,即需要在初始页面加载以及 turbolinks:load 上触发。我在 SO 上提出了一个关于此问题的问题,https://dev59.com/yp3ha4cB1Zd3GeqPZ9Ds。你有什么更深入的见解吗?你是否正在使用 jquery-turbolinks(我是)。唯一好的事情是它确保您的代码是幂等的。 - Obromios
2
Rails 6有所不同吗? - stevec
显示剩余6条评论

68

原生JavaScript:

document.addEventListener("turbolinks:load", function() {
    console.log('It works on each visit!');
});

2
turbo:load 用于 Turbo - Dorian

14

在 Rails 5 中,最简单的解决方案是使用:

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

不使用$(document).ready。很好用。


12
不要将 ready 添加到列表中,否则函数将被执行两次。根据 https://github.com/turbolinks/turbolinks/#observing-navigation-events 的说法,您应该像这样做: $(document).ready(function() { $(document).on('turbolinks:load', function() {} ) }) - Xiaohui Zhang
@XiaohuiZhang 你确定这样会起作用吗?因为如果 $(document).ready 被触发,至少在我的场景中,我不需要 turbolinks:load - Milad.Nozari
@XiaohuiZhang 如果你的脚本需要在带有 turbolinks 和不带 turbolinks 的页面上工作,那么它将无法在不带 turbolinks 的页面上工作,因为它需要 turbolinks:load 事件来执行代码。 - cercxtrova
@escanxr 它可以同时工作,你可以试一下。因为Turbolinks总是在Turbolinks页面或非Turbolinks页面上触发“turbolinks:load”事件。 - Xiaohui Zhang
2
@XiaohuiZhang,我尝试了Turbolinks 5,但是没有用。如果页面上禁用turbolinks,则只会触发“ready”事件。如果有turbolinks,则代码会调用两次。 - cercxtrova

9
这是我的解决方案,重写jQuery.fn.ready,然后$(document).ready就可以在不做任何更改的情况下正常工作:
jQuery.fn.ready = (fn)->
  $(this).on 'turbolinks:load', fn

这正是我所需要的。 这也适用于依赖于“document”回调的外部库。 为什么要点踩? 只要在整个应用程序中使用turbolinks,这应该是安全的,对吗? - Dylan Vander Berg

3

(对于CoffeeScript)

我使用: $(document).on 'turbolinks:load', ->

而不是: $(document).on('turbolinks:load', function() {...})

(这样做可以使代码更简洁易懂)

我已经做过了,但是我仍然遇到了这个问题,就像@inye所说的那样:https://github.com/mkhairi/materialize-sass/issues/130。对我来说,使用JS或Coffee并没有真正产生任何区别,至少不是很明显的区别。 - alexventuraio
2
各位好,这个答案总体上有什么问题? - atw
我的猜测是这是Coffeescript而不是本地的Javascript?我给了它一个+1,因为这正是我正在做的,而且在我的Coffeescript文件中它也起作用。 - aarona
是的!它是用于Coffeescript的 :)。我的错误是没有指定它。 - fcabanasm

3

纯现代 JavaScript:

const onLoad = () => {
  alert("works")
}

document.addEventListener("load", onLoad)
document.addEventListener("turbolinks:load", onLoad)

使用 Turbo 后,它变成了 turbo:load

2

在“生产”环境中怎么样?你测试过了吗?有些人说它只在“开发”模式下运行良好。 - alexventuraio
6
这个宝石已经被废弃了。 - Mauro

1

在我们等待修复这个非常酷的宝石之前,我通过修改以下内容来继续前进;

  addCallback: (callback) ->
if $.turbo.isReady
  callback($)
$document.on 'turbo:ready', -> callback($)

to:

  addCallback: (callback) ->
if $.turbo.isReady
  callback($)
$document.on 'turbolinks:load', -> callback($)

我还不清楚这个解决了什么问题,但在初步检查中似乎表现良好。


0
使用轻量级的 gem jquery-turbolinks
它可以使 $(document).ready() 在不改变现有代码的情况下与 Turbolinks 一起工作。
或者,您可以将 $(document).ready() 更改为以下之一:
$(document).on('page:fetch', function() { /* your code here */ });

$(document).on('page:change', function() { /* your code here */ });

根据您的实际情况选择更为合适的方案。

jquery-turbolinks暂不支持Turbolinks 5 https://github.com/kossnocorp/jquery.turbolinks/issues/56 - AndrewH
你说得对,@AndrewH!希望很快能够添加支持。 - Vadim
2
jquery-turbolinks gem已被弃用。 - Nathan V

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接