Turbolinks 在加载下一页内容之前调用 "load" 个脚本

Turbolinks invokes "load" scripts just before load content of next page

拥有:
- 页面 A 是纯粹的 HTML 没有脚本;
- 页面 B 在 Turbolinks "turbolinks:load" 事件上有一些 Javascript。

正在加载页面 B 并在 "turbolinks:load" 上正确设置脚本 运行。 现在我在页面 B 上并单击 link 到页面 A。这次来自 "turbolinks:load" 的脚本在加载页面 A 内容之前触发。

这是错误还是某些定义的行为?

要重现的简单示例 Rails 代码。
控制器:

#app/controllers/turbobugs_controller.rb
class TurbobugsController < ApplicationController
  def a
    render layout: false
  end

  def b
  end
end

路线:

namespace :turbobugs do
  get :a
  get :b
end

观看次数:

#app/views/turbobugs/a.html.haml
%h1
  No scripts here
= link_to turbobugs_b_path, turbobugs_b_path

#app/views/turbobugs/b.html.haml
= link_to turbobugs_a_path, turbobugs_a_path
%script
  document.addEventListener("turbolinks:load", function() { console.log('I am script in page B running on window.location: ' + window.location); });

正在打开页面 B 并在控制台中查看:

"I am script in page B running on window.location: http://localhost:3000/turbobugs/b"

然后跟随link到页面A并在日志中查看:

"I am script in page B running on window.location: http://localhost:3000/turbobugs/a"

为什么 :) ?

另请注意,该脚本确实在页面 B 的内容上开始 运行,但在 A 加载(或开始加载或其他任何内容)之前终止(如果花费的时间太长或某些 Ajax 异步)。 ..).

这是定义的行为。假设您的资产标签(JS 或 CSS)具有 data-turbolinks-track="reload" 属性,Turbolinks 在发现页面 A 上缺少脚本时会完全重新加载页面。根据 Turbolinks README

This ensures that users always have the latest versions of your application’s scripts and styles.

您可以通过从资产标签中删除 data-turbolinks-track="reload" 来更改此行为,但请注意上述内容。

就观察到的日志记录行为而言,Turbolinks 会在每次访问时执行特定的程序。对于这种情况,大致可以概括为:

  1. 请求新内容
  2. 改变URL
  3. 检查跟踪元素中的任何差异
  4. 如果有差异则完全重新加载,否则呈现新内容
  5. 运行 complete 函数

部分complete过程是为了触发turbolinks:load,即使页面重新加载,事件仍然触发只是在之前发生了。


附带说明一下,在使用 Turbolinks 时,向内联脚本添加事件侦听器可能会导致一些意外行为。

传统上,内联脚本表明代码只会在给定页面上执行——当用户从一个位置导航到下一个位置时,事件侦听器将被销毁。使用 Turbolinks 时情况并非如此——事件侦听器会一直存在,除非它们被删除。

例如,如果您在内联脚本中为 turbolinks:load 添加一个事件侦听器,它将在每次后续页面加载时执行,除非被删除。更重要的是,如果用户重新访问带有内联脚本的页面,监听器将再次被绑定,导致处理程序被多次调用。