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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/18769109/
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-10-27 13:10:04  来源:igfitidea点击:

Rails 4 turbo-link prevents jQuery scripts from working

javascriptruby-on-rails-4turbolinks

提问by emersonthis

I'm building a Rails 4 app and I have a few scattered js files that I'm trying to include "the rails way". I moved jquery plugins into the /vendor/assets/javascripts and I updated the manifest (application.js) to require them. When I load the pages locally I see that they appear correctly.

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

However, I'm getting inconsistent behavior from one of the scripts that's compiled. I have a controller-specific js file called projects.js which is referenced in the application.js via the use of require_tree .:

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

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

I see the file is included correctly, and it works... half the time. The other half of the time, the stuff in projects.js doesn't seem to do anything (it's mostly jquery animations and some ajax requests). When it doesn't work, I'll click buttons a couple times, nothing will happen, and then I'll throw this error:

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

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

This never happened when the scripts were in the individual views (the wrong way), so I'm fairly certain the problem is not with my javascript code. One other potentially relevant details is that the stuff in projects.js is wrapped in a $(document).ready(function(){. Also, I'm testing in development mode so the javascripts and css are not combined by the asset pipeline.

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

Any idea what's going on here? I'm new to Rails but I've done my best to follow all the conventions.

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

Update!

更新!

It's predictable whenmy project scripts don't work. The first page load works every time. Then I click one link to a new page which uses my project.js behaviors and the secondpage never works. I click a few times and eventually throw the error above. I'm still not sure why, but I'm suspecting this is related to turbo-linking.

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

回答by mu is too short

$(document).ready(function(){doesn't really work with Turbolinks. Turbolinks:

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

... makes following links in your web application faster. Instead of letting the browser recompile the JavaScript and CSS between each page change, it keeps the current page instance alive and replaces only the body and the title in the head.

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

So the page is only loaded once and then pieces are replaced as needed. Since the page is only loaded once, your $(document).ready()callbacks are only triggered when the site is initially visited, you won't get more document-ready events when switching pages because Turbolinks doesn't actually switch pages. From the fine manual:

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

With Turbolinks pages will change without a full reload, so you can't rely on DOMContentLoadedor jQuery.ready()to trigger your code. Instead Turbolinks fires events on document to provide hooks into the lifecycle of the page.

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

You probably want to listen for one of the Turbolinks events instead:

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

  • page:changethe page has been parsed and changed to the new version and on DOMContentLoaded
  • [...]
  • page:loadis fired at the end of the loading process.
  • page:change该页面已被解析并更改为新版本和 DOMContentLoaded
  • [...]
  • page:load在加载过程结束时触发。

page:changeis usually what you're looking for as it is triggered when loading a fresh page and restoring a page from the Turbolinks page cache.

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

You might want to turn off Turbolinks until you've had time to review allof your JavaScript and you've done a full QA sweep. You should also test your site's speed to see if it is worth using at all.

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

Another option would be to use jquery.turbolinksto patch up things for you. I haven't used this but other peopleare using it to good effect.

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

回答by Ole Henrik Skogstr?m

A solution to this is already available at this railscast

railscast已提供解决方案

Here is one example (the one i like to use).

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

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

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

There is also a gemthat solves this issue in a way that lets you keep doing it the old way. It works really well :)

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

回答by Shawn Wilson

I realize this Answer is REAAAAAAALLLLLLLYYYYY Late... but I figured I'd add it.

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

I just had this issue last week.. While trying to get Foundation to work..

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

First I added:

首先我补充说:

gem 'jquery-turbolinks'

Then Placed it in application.jslike so:

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

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

and then I added this right below it:

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

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

});

and everything worked for me. Hope this helps!

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