47

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

但是,我从一个已编译的脚本中得到了不一致的行为。我有一个名为 projects.js 的特定于控制器的 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 行为的新页面,而第二个页面永远不会工作。我点击了几次,最终抛出了上面的错误。我仍然不确定为什么,但我怀疑这与涡轮链接有关。

4

3 回答 3

44

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

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

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

使用 Turbolinks,页面会在没有完全重新加载的情况下发生变化,因此您不能依赖DOMContentLoadedjQuery.ready()触发您的代码。相反,Turbolinks 会在文档上触发事件以提供进入页面生命周期的挂钩。

您可能想要监听其中一个 Turbolinks 事件:

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

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

在您有时间查看所有JavaScript 并且完成完整的 QA 扫描之前,您可能希望关闭 Turbolinks 。您还应该测试您网站的速度,看看它是否值得使用。

另一种选择是使用jquery.turbolinks为你修补东西。我没用过,但其他人用它效果很好。

于 2013-09-12T16:59:14.307 回答
28

这个railscast已经提供了一个解决方案

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

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

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

还有一个 gem可以解决这个问题,让您可以继续使用旧方法。它工作得很好:)

于 2013-11-11T19:24:24.270 回答
1

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

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

首先我补充说:

gem 'jquery-turbolinks'

然后application.js像这样放置它:

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

然后我在它下面添加了这个:

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

});

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

于 2016-11-03T07:02:14.413 回答