javascript - 使用 Turbolinks 5 重构内联 <script> 元素

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

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

在我的应用程序中,我有包含 <script> 的 View 文件元素,我想让它们正确地与 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 状态”和“引导客户端模型”是什么意思?

最佳答案

如果您的内联脚本包含在 <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

希望对您有所帮助!

关于javascript - 使用 Turbolinks 5 重构内联 &lt;script&gt; 元素,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55174436/

相关文章:

ruby-on-rails - 丢失了我的 schema.rb!可以再生吗?

ruby-on-rails - PostgreSQL 错误 : could not connect to database template1: could not connect to server:

ruby-on-rails-5 - rails 用 cancancan 管理

javascript - 如何通过 html id 将两个随机数传递给 JS 中的函数?

javascript - Uncaught ReferenceError : jasmineRequire is not defined

ruby-on-rails - 如何在生产模式下使用 Rails 3.1 设置一个完整的 "hello world"站点?

ruby-on-rails - ruby rails : How can I specify runner script environment

ruby-on-rails - Rails 5 升级后性能大幅下降

javascript - 在 Canvas Cylinder 中动态填充颜色我收到错误消息,因为最大宽度未定义

javascript - 根据字符串检查 <a> 元素文本值