Rails 5 - turbolinks 5,页面渲染时未加载部分JS

12

我有一个Rails应用程序,最近升级到5.0.0.RC1。大部分过渡很顺利,但是我在使用新的Turbolinks时遇到了一些麻烦。在我的应用程序中,例如使用了这个 gem:


gem 'chosen-rails'

我的 application.js 文件看起来像这样:

//= require jquery
//= require jquery.turbolinks
//= require jquery_ujs
//= require best_in_place
//= require tether
//= require bootstrap
//= require chosen-jquery
//= require_tree .
//= require turbo links
当我点击链接并渲染视图时,我的 chosen-querybest_in_place 不太好用)在初始加载时不起作用,但如果我强制刷新页面则可以正常工作。下面是我得到的结果的图像: How it looks now 这是我想要的效果的图片: enter image description here 同样,如果我进行常规的 redirect_to ...,则期望的外观仅在进行硬刷新后才能正常显示。
我的下拉列表的代码如下:
= select_tag :screen, options_from_collection_for_select(@screens, "id",  "name"), id: "screen-selection", prompt: "Jump to screen", class: 'form-control  chosen-select', style: "max-width: 250px !important"

重定向 (redirect_to) 后的结果如下所示:

<select name="screen" id="screen-selection" class="form-control chosen-select"  style="max-width: 250px !important">[...]</select>

...之后进行了一次艰难的页面重新加载,我得到了以下结果:

<select name="screen" id="screen-selection" class="form-control chosen-select"  style="max-width: 250px !important; display: none;">[...]</select>

<div class="chosen-container chosen-container-single" style="width: 190px;" title="" id="screen_selection_chosen"><a class="chosen-single"><span>Jump to screen</span><div><b></b></div></a><div class="chosen-drop"><div class="chosen-search"><input type="text" autocomplete="off"></div><ul class="chosen-results"><li class="active-result result-selected" data-option-array-index="0" style="">Jump to screen</li><li class="active-result" data-option-array-index="1" style="">tests</li></ul></div></div>

在一个 .coffee 文件中,我尝试像这样初始化chosen

# enable chosen js
$('#screen-selection').chosen({
  width: '190px'
})

我做错了什么,有什么想法吗?

7个回答

29

通过使用turbolinks,JavaScript仅被加载一次。在强制刷新时,chosen可以工作,因为整个页面被重新渲染。一旦单击链接,turbolinks会劫持请求并将其转换为ajax请求(而不是完全刷新页面)。一旦请求到达,turbolinks仅替换页面的部分,使JS保持原状。

要解决这个问题,您需要将您的chosen初始化器包装在turbolinks:load事件中,像这样:

$(document).on('turbolinks:load', function() {
  $('#screen-selection').chosen({
    width: '190px'
  })
})

有关更多信息,请参见https://github.com/turbolinks/turbolinks#installing-javascript-behavior


2
但是有一个很大的问题:turbolinks会将页面存储在缓存中,因此您应该确保您的JavaScript代码是幂等的,否则您可能会在页面上拥有多个选择器(或在其他情况下,一个元素上附加了多个事件处理程序)。有关更多信息,请阅读https://www.crossplatform.net/rails/article/should-you-disable-turbolinks/idempotent-transformation/。 - Marek Příhoda
除非将处理程序附加到文档,否则不必太担心几个事件处理程序部分。否则,在Turbolinks 5中,<body>会被克隆并恢复,而不会保留任何相关的处理程序等... - Brendon Muir

8

5

我花费了很多心思才找到一种方法使我的javascript代码都能正常工作。最初我试着使用gem jquery.turbolinks,参考了这个视频:如何升级到turbolinks 5,但我发现在同一页面中显示图像的lightbox并没有正常工作。所以,在彻底禁用Turbolinks之前,我在github页面上花费了更多时间尝试了这个:

<div data-turbolinks="false">
  <a href="/">Disabled</a>
</div>

您需要在每个链接上放置此代码,以便javascript需要重新加载页面才能工作。

也许这不是最好的解决方案,但这使我的头痛减轻了。


0

我尝试自己解决这个问题,并找到了适合我的解决方案。

我的问题是,我有一个带有评论“引用”功能的论坛。使用turbolinks 5后,我得到了几个事件监听器,并最终在我的编辑器中获得了同一评论的多达四个引用。

我阅读了幂等性并在此处找到了解决方案:如何使jQuery `bind`或`on`事件处理程序具有幂等性

我创建了(实际上是复制了)一个全局函数,我在我的globals.coffee文件中用于事件。

$.fn.event = (name, fn) ->
  @unbind(name).bind name, fn

它可以工作。

我的函数看起来像这样:

$('.quote').event 'click', (event) ->
 do something 

所有荣誉归 Pointy 所有,他提供了解决方案。

链接到 turbolinks 和幂等性


0

这是我的做法...使用Turbolinks5来防止多次加载。

var ready = function () {

   if ($.turboAlreadyLoaded) {

      $('#screen-selection').chosen({
        width: '190px'
      })
   }
$.turboAlreadyLoaded = true;

}
$(document).ready(ready);
$(document).on("turbolinks:load", ready);

0
Turbolinks和jquery有点让人头疼。与其在文档准备就绪时调用一个操作,不如在页面加载时调用更好,因为使用turbolinks时,在浏览网站时它不会重新加载整个文档。类似这样的代码可能会起作用:
$(document).on('page:load', function() {
  $('#screen-selection').chosen({
    width: '190px'
  })
}

4
这个问题涉及到“新Turbolinks”(即Turbolinks 5),它实际上会破坏使用除了“turbolinks:load”之外的其他事件的应用程序。因此,您建议的方法在Rails和Turbolinks 5中不再适用。 - user3670743

0

我尝试着自己解决了这个问题,并找到了一个适合我的解决方案。同时也希望能对其他人有所帮助。

(function () {
    $('#screen-selection').chosen({
        width: '190px'
    })
})();

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