如何在Rails中使用Coffeescript绑定jQuery的onclick事件?

9
我意识到我可能需要全局声明onclick事件,但我试图避免在编译时使用--bare标签。
这是我试图让它工作的代码...
jQuery ->
  $('.tabs_image').click ->
    $(this).addClass('tabs_selected')
    $('.tabs_video').removeClass('tabs_selected')
    $('#image_upload_form').show()
    $('#video_upload_form').hide()
    return

  $('.tabs_video').click ->
    $(this).addClass('tabs_selected')
    $('.tabs_image').removeClass('tabs_selected')
    $('#image_upload_form').hide()
    $('#video_upload_form').show()
    return

  return

在谷歌浏览器中,一旦页面进行硬刷新(点击刷新),它就能正常工作。

我尝试过$ =>$(document).ready ->$(document).ready =>


1
一旦页面在Chrome浏览器中刷新,它就可以正常工作。如果内容是动态添加的,您将需要使用委托事件 - Jonathan Lonowski
@JonathanLonowski 在这种情况下,内容已经存在;它不是动态添加的。不过我会尝试一下。这是在一个Rails应用程序中,所以我不知道那是否会产生影响。 - Crimbo
3个回答

7
我找到了问题的症结 - 我的Coffeescript没问题,是因为一个叫做Turbolinks的gem导致代码没有触发。它保持当前页面实例的活动状态,并仅替换头部中的body和title,这意味着您不能依赖于DOMContentLoadedjQuery.ready()来触发您的代码。这就是为什么当页面被强制刷新(点击刷新)时脚本似乎会起作用的原因。

对于那些使用Turbolinks的人

  • 如果你想退出特定链接

在链接的父容器中添加data-no-turbolink,如下所示...

<a href="/">Home (via Turbolinks)</a>
<div id="some-div" data-no-turbolink>
  <a href="/">Home (without Turbolinks)</a>
</div>
  • 如果您有很多现有的 JavaScript 绑定在 jQuery.ready()

使用事件钩子 page:change,您可以用 $(document).on 'page:change', -> 或更好的是 $(document).on 'ready page:change', -> 来替换 jQuery.ready();更好是因为它意味着即使 turbolinks 没有运行(可能是由于旧的浏览器版本),调用仍将由于 ready 存在而触发。

最好使用 page:change 而不是 page:load。前者事件钩子在页面从服务器或客户端缓存中加载时触发,而后者事件钩子仅在新的 body 元素被加载到 DOM 中时触发 (source)。

...或者...

您可以使用 jquery-turbolinks gem。

gem 'jquery-turbolinks'

bundle install,然后按照以下顺序将其添加到JavaScript清单文件中:

//= require jquery
//= require jquery.turbolinks
//= require jquery_ujs
//
// ... your other scripts here ...
//
//= require turbolinks

5
我认为你应该使用事件委托。试试这样做,看看是否能获得更好的结果:
$ ->
  $('body').on 'click', '.tabs_image', ->
    # do stuff

“我认为你应该使用事件委托。” 鉴于“在这种情况下,内容已经存在;它不是动态添加的。” - Kevin B
@nick 谢谢,我已经尝试过了,但没有帮助。我有一种感觉是在Rails中发现了一个bug。 - Crimbo
现在我知道这是因为Turbolinks,使用钩子page:load可以通过将您的$ ->替换为$(document).on 'page:load', ->$(document).on 'ready page:load', ->来实现。 - Crimbo
@KevinB 因为如果有多个匹配的选择器,你会多次附加相同的事件。这可能会导致内存泄漏。对于大多数应用程序来说,这可能是边缘情况,但通常使用事件委托来应对这些潜在挑战是没有问题的。PPK在这里触及了它,在“焦点问题”之前的句子中:http://www.quirksmode.org/blog/archives/2008/04/delegating_the.html - Nick Johnson

0

使用$(document).on 'ready page:load', ->而不是jQuery ->来加载DOM,您可以在Rails文档中了解更多信息。


最好使用 page:change 而不是 page:load来源 - Crimbo

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