Turbolinks 5,jQuery 3:无论如何要避免 event.off(...).on(...) 重复事件?

Turbolinks 5, jQuery 3: anyway to avoid event.off(...).on(...) for duplicate events?

我正在使用 Turbolinks 5 和 jQuery 3 构建一个 Rails 4 应用程序。

在我加载应用程序的主要 global.coffee 上,我使用 CoffeeScript class 来抽象一些事件处理:

# app/javascripts/global.coffee
$(document).on "turbolinks:load", ->
  App.MD.ExpansionPanel.init()

# app/javascripts/expansion_panel.coffee
class App.MD.ExpansionPanel
  @init: () ->
    $(document).off("click", "[data-behavior='expansion-panel-toggle']").on "click", "[data-behavior='expansion-panel-toggle']", (e) ->
      $panel = $(this).closest("[data-behavior='expansion-panel']")
      $details = $panel.find("[data-behavior='expansion-panel-details']")

      if $panel.attr("data-state") == "expanded"
        $panel.attr("data-state", "collapsed")
      else
        $panel.attr("data-state", "expanded")

# Some sample HTML (clicking any toggle element toggles between the summary or detail view)
<div data-behavior="expansion-panel">
  <div data-behavior="expansion-panel-summary">
    <div data-behavior="expansion-panel-toggle">Summary Toggle</div>
  </div>
  <div data-behavior="expansion-panel-details">
    <div data-behavior="expansion-panel-toggle">Details Toggle</div>
  </div>
</div>

问题是,事件触发了多次,而我的 expand/collapse 面板会切换这两个事件,从而使面板返回到原始状态。

我通过使用 .off("click", ...).on("click", ...) 先删除 click 事件然后重新添加它来解决这个问题,但有些事情告诉我这不是一个很好的解决方案,因为我'以前从来没有这样做过。

是否有更高效的方法来设置此事件处理程序?

我通过 AJAX 添加了动态内容,这就是我将事件添加到 document 本身而不是某些父上下文的原因。

似乎 $(document).on('click','.selector', function(){...}) 应该声明在 $(document).on('turbolinks:load', function(event) {..}); 之外

这引导我找到解决方案:https://www.rubydoc.info/gems/jquery-turbolinks/2.1.0#Events_firing_twice_or_more

当前的文档说了类似的话:

When possible, avoid using the turbolinks:load event to add other event listeners directly to elements on the page body. Instead, consider using event delegation to register event listeners once on document or window. -- https://github.com/turbolinks/turbolinks#observing-navigation-events

我有一个类似的案例(一个关闭-canvas 菜单),它只适用于首先取消绑定 (*.off()) 事件。现在在 turbolinks:load 之外绑定事件,它按预期工作。