使用Turbolinks时重构内联元素5

问题描述 投票:2回答:1

我将我的应用程序迁移到Ruby on Rails 5(v5.2.2),我正在尝试使用Turbolinks 5(v5.2.0)。

在我的应用程序中,我有查看包含<script>元素的文件,我想让它们正确使用Turbolinks(其documentation声明避免脚本元素并使用turbolinks:load事件)。我要做什么?

也就是说,例如,我有:

# app/views/.../_partial_template.html.erb
<script type="text/javascript">
  $(document).ready(function () { 
    $.ajax({...})
  });

  // Note: I tried to use $(document).on('turbolinks:load', function() {...});
  // and it seems that the JS code runs twice (or more) on every page load.
  // I also tried to use <script type="text/javascript" data-turbolinks-eval="false">...</script>
  // without success.
</script>

我应该如何重构上面的代码以使其适用于Turbolinks?


奖金:

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

javascript ruby-on-rails ruby-on-rails-5 turbolinks turbolinks-5
1个回答
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

希望有所帮助!

© www.soinside.com 2019 - 2024. All rights reserved.