使用Turbolinks 5时重构内嵌<script>元素

时间:2019-03-15 01:46:19

标签: javascript ruby-on-rails ruby-on-rails-5 turbolinks turbolinks-5

我将应用程序迁移到了Ruby on Rails 5(v5.2.2),并且试图使用Turbolinks 5(v5.2.0)。

在我的应用程序中,我查看了包含   // 没有成功。

我应该如何重构以上代码以使其能够与Turbolinks一起正常使用?


奖金:

Turbolinks 文档说:您可以使用内联主体脚本来设置每页JavaScript状态或引导客户端模型。 “每页JavaScript状态”和“引导客户端模型”是什么意思?

1 个答案:

答案 0 :(得分:1)

如果您的内联脚本包含在<body>的底部(或者它们没有立即操纵DOM),那么您也许可以从$(document).ready…函数中删除代码,并使它们按预期工作。

通常不建议使用内联脚本,因为传统上它们指示代码仅在包含它的页面上运行,并且当用户离开时,任何事件侦听器都将被自动销毁。但是,在Turbolinks应用程序中并非如此。如果您在嵌入式脚本中添加事件监听器(但不要删除它),它将继续监听并在后续页面加载中运行。通过以这种方式设置turbolinks:load事件监听器可以发现,处理程序在随后的页面加载时触发,并且在重新访问第一页时,再次添加了事件监听器,从而导致重复调用。

关于设置“每页JavaScript状态”和“引导客户端模型”,假设您有一个日历页面,希望使用某些JavaScript进行增强。您可能有一个Calendar JavaScript类来处理此问题,因此您可以包括以下内容以使用一些JSON引导它:

<script>new Calendar(<%= @calendar.to_json %>)</script>

(请记住,在Calender类中设置的所有添加的事件侦听器都可能在某个时候被销毁,例如turbolinks:before-cache)。

这说明了这个想法,但是在这种情况下,更好的方法可能是建立一个查找日历元素的系统,然后在DOM中实例化它们。例如:

<div data-component="calendar" data-props="<%= @calendar.to_json %>">…</div>

然后在您的JavaScript中(包含在应用程序捆绑包中):

;(function () {
  var calendar

  $(document).on('turbolinks:load', function () {
    var $el = $('[data-component=calendar]')
    if ($el.length) calendar = new Calender($el.data('props'))
  })

  $(document).on('turbolinks:before-cache', function () {
    if (calendar) {
      calendar.destroy() // to teardown any event listeners etc
      calender = null
    }
  })
})()

这种方法可以推广,在这里我已经完成了一个实现:https://stackoverflow.com/a/44057187/783009

希望有帮助!