Rails 4 turbo-link 阻止 jQuery 脚本工作

IT技术 javascript ruby-on-rails-4 turbolinks
2021-02-09 23:29:40

我正在构建一个 Rails 4 应用程序,我有一些分散的 js 文件,我试图将它们包含在“rails 方式”中。我将 jquery 插件移动到 /vendor/assets/javascripts 并更新了清单 (application.js) 以要求它们。当我在本地加载页面时,我看到它们显示正确。

但是,我从编译的其中一个脚本中得到了不一致的行为。我有一个特定于控制器的 js 文件,名为 projects.js,它在 application.js 中通过使用require_tree .

//= require jquery
//= require jquery_ujs
//= require turbolinks
//= require bootstrap.min
//= require jquery.form.min
//= require_tree .

我看到文件被正确包含,并且它可以工作......一半时间。另一半时间,projects.js 中的东西似乎没有做任何事情(主要是 jquery 动画和一些 ajax 请求)。当它不起作用时,我会点击按钮几次,什么都不会发生,然后我会抛出这个错误:

Uncaught TypeError: Cannot read property 'position' of null 
turbolinks.js?body=1:75

当脚本处于单个视图中时(错误的方式),这从未发生过,所以我相当确定问题不在于我的 javascript 代码。另一个可能相关的细节是 projects.js 中的内容被包装在$(document).ready(function(){. 此外,我正在开发模式下进行测试,因此资产管道不会将 javascripts 和 css 组合在一起。

知道这里发生了什么吗?我是 Rails 的新手,但我已尽力遵循所有约定。

更新!

我的项目脚本不起作用时,这是可以预测的每次加载第一页都有效。然后我单击一个链接到一个使用我的 project.js 行为的新页面,而第二个页面从不工作。我点击了几次,最终抛出了上面的错误。我仍然不确定为什么,但我怀疑这与涡轮链接有关。

3个回答

$(document).ready(function(){不适用于 Turbolinks。涡轮链接

... 使您的 Web 应用程序中的链接速度更快。它不是让浏览器在每次页面更改之间重新编译 JavaScript 和 CSS,而是让当前页面实例保持活动状态并仅替换正文和头部的标题。

所以页面只加载一次,然后根据需要替换部分。由于页面仅加载一次,因此您的$(document).ready()回调仅在最初访问站点时触发,因此在切换页面时您不会获得更多文档就绪事件,因为 Turbolinks 实际上并不切换页面。精美的手册

使用 Turbolinks 页面将无需完全重新加载即可更改,因此您不能依赖DOMContentLoadedjQuery.ready()触发您的代码。相反,Turbolinks 在文档上触发事件以提供进入页面生命周期的钩子。

您可能想要监听 Turbolinks 事件之一:

  • page:change 该页面已被解析并更改为新版本和 DOMContentLoaded
  • [...]
  • page:load 在加载过程结束时触发。

page:change 通常是您要查找的内容,因为它是在加载新页面并从 Turbolinks 页面缓存中恢复页面时触发的。

您可能想要关闭 Turbolinks,直到您有时间检查所有JavaScript 并完成完整的 QA 扫描。您还应该测试您网站的速度,看看它是否值得使用。

另一种选择是使用jquery.turbolinks为您修补内容。我没有用过这个,但其他人正在使用它,效果很好。

再想一想,你的答案解决了这个问题的问题。Turbo-linking 阻止了就绪事件。所以我创建了一个新问题来解决应该如何完成的后续问题:stackoverflow.com/questions/18770517/...
2021-03-20 23:29:40
对于 rails 5,你可以简单地说 $(document).on('turbolinks:load', function() { ... });
2021-03-21 23:29:40
该Turbolinks文档说,这引发了自己page:...对事件document这样$(document).on('page:change', function() { ... })和这样。
2021-04-10 23:29:40
谢谢!!你会从我的更新(刚刚添加)中看到你所说的与我所看到的完全吻合。但是,我对我的“特定于页面”的 js 代码应该包含什么(如果有的话)有点困惑。例如,如果我将所有内容都放在 application.js 中,我是否应该直接跳入事件等?No $(document).ready...?
2021-04-11 23:29:40

railscast已提供解决方案

这是一个例子(我喜欢使用的那个)。

ready = ->
  # ..... your js

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

还有一个 gem可以让您继续以旧方式解决这个问题。它真的很好用 :)

不,这是 CoffeeScript。有关如何翻译的示例,请将上述代码粘贴到此页面的右侧文本框中:js2.coffee
2021-03-14 23:29:40
这是在使用 Haml 吗?我不确定如何将您的答案翻译成常规的 javascript
2021-03-25 23:29:40
对宝石的伟大呼吁!
2021-03-27 23:29:40

我意识到这个答案是 REAAAAAAALLLLLLLYYYYY 晚了......但我想我会添加它。

我上周刚遇到这个问题..在试图让 Foundation 工作时..

首先我补充说:

gem 'jquery-turbolinks'

然后application.js像这样放置它

//= require jquery.turbolinks
//= require jquery_ujs
//= require turbolinks
//= require_tree .

然后我在它的正下方添加了这个:

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

});

一切都对我有用。希望这可以帮助!

你真的不再需要jquery-turbolinksgem 了。新的 turbolinks 5 工作正常
2021-03-18 23:29:40