Navigate with Turbo Drive


Navigate with Turbo Drive

Turbo Drive is the part of Turbo that enhances page-level navigation. It watches for link clicks and form submissions, performs them in the background, and updates the page without doing a full reload. It’s the evolution of a library previously known as Turbolinks.
Turbo Drive是Turbo增强页面级导航的一部分。它监视链接点击和表单提交,在后台执行,并在不进行完全重新加载的情况下更新页面。这是以前称为Turbolinks的库的演变。


Page Navigation Basics
Turbo Drive models page navigation as a visit to a location (URL) with an action.

Visits represent the entire navigation lifecycle from click to render. That includes changing browser history, issuing the network request, restoring a copy of the page from cache, rendering the final response, and updating the scroll position.

There are two types of visit: an application visit, which has an action of advance or replace, and a restoration visit, which has an action of restore.
Turbo Drive将页面导航建模为通过操作访问某个位置(URL)。
访问表示从单击渲染的整个导航生命周期。这包括更改浏览器历史记录发出网络请求从缓存恢复页面副本呈现最终响应以及更新滚动位置
访问有两种类型:应用程序访问(具有提前或替换操作)和恢复访问(具有恢复操作)。

Application Visits
Application visits are initiated by clicking a Turbo Drive-enabled link, or programmatically by calling Turbo.visit(location).

An application visit always issues a network request. When the response arrives, Turbo Drive renders its HTML and completes the visit.

If possible, Turbo Drive will render a preview of the page from cache immediately after the visit starts. This improves the perceived speed of frequent navigation between the same pages.

If the visit’s location includes an anchor, Turbo Drive will attempt to scroll to the anchored element. Otherwise, it will scroll to the top of the page.

Application visits result in a change to the browser’s history; the visit’s action determines how.
通过单击启用Turbo Drive的链接或通过调用 Turbo.visit(location)以编程方式启动应用程序访问。
应用程序访问总是发出网络请求。当响应到达时,Turbo Drive renders 其HTML并完成访问。
如果可能,Turbo Drive将在访问开始后立即从缓存中呈现页面预览。这提高了相同页面之间频繁导航的感知速度。
如果访问的位置包括锚,Turbo Drive将尝试滚动到锚定元素。否则,它将滚动到页面顶部。
应用程序访问导致浏览器历史记录的更改;访问的行为决定了如何。

The default visit action is advance. During an advance visit, Turbo Drives pushes a new entry onto the browser’s history stack using history.pushState.

Applications using the Turbo Drive iOS adapter typically handle advance visits by pushing a new view controller onto the navigation stack. Similarly, applications using the Android adapter typically push a new activity onto the back stack.
默认就诊操作为“advance”。在提前访问期间,Turbo Drives使用history.pushState将新条目推送到浏览器的历史堆栈中。
使用Turbo Drive iOS适配器的应用程序通常通过将新的视图控制器推到导航堆栈上来处理提前访问。
类似地,使用Android适配器的应用程序通常会将一个新的活动推到后台。

You may wish to visit a location without pushing a new history entry onto the stack. The replace visit action uses history.replaceState to discard the topmost history entry and replace it with the new location.

To specify that following a link should trigger a replace visit, annotate the link with data-turbo-action="replace":
您可能希望访问某个位置,而不将新的历史记录条目推到堆栈上。替换访问操作使用history.replaceState丢弃最上面的历史记录条目,并将其替换为新位置。
要指定以下链接应触发替换访问,请使用data turbo action=“replace”注释链接:

<a href="/edit" data-turbo-action="replace">Edit</a>
To programmatically visit a location with the replace action, pass the action: "replace" option to Turbo.visit:
data-turbo-action="replace" 替换不要将我的访问作为历史记录。

Turbo.visit("/edit", { action: "replace" })
Applications using the Turbo Drive iOS adapter typically handle replace visits by dismissing the topmost view controller and pushing a new view controller onto the navigation stack without animation.
使用Turbo Drive iOS适配器的应用程序通常通过取消最上面的视图控制器并将新的视图控制器推到导航堆栈上而无需动画来处理替换访问。

Restoration Visits
Turbo Drive automatically initiates a restoration visit when you navigate with the browser’s Back or Forward buttons. Applications using the iOS or Android adapters initiate a restoration visit when moving backward in the navigation stack.
当您使用浏览器的后退或前进按钮导航时,Turbo Drive会自动启动恢复访问(第二类访问)。使用iOS或Android适配器的应用程序在导航堆栈中向后移动时启动恢复访问。

If possible, Turbo Drive will render a copy of the page from cache without making a request. Otherwise, it will retrieve a fresh copy of the page over the network. See Understanding Caching for more details.

Turbo Drive saves the scroll position of each page before navigating away and automatically returns to this saved position on restoration visits.

Restoration visits have an action of restore and Turbo Drive reserves them for internal use. You should not attempt to annotate links or invoke Turbo.visit with an action of restore.
如果可能,Turbo Drive将从缓存中呈现页面的副本,而无需发出请求。否则,它将通过网络检索页面的新副本。有关详细信息,请参见了解缓存。
Turbo Drive在导航离开之前保存每个页面的滚动位置,并在恢复访问时自动返回到此保存位置。
Restoration visits
问具有恢复功能,Turbo Drive将其保留供内部使用。您不应尝试注释链接或调用Turbo。通过恢复操作访问。

Canceling Visits Before They Start
Application visits can be canceled before they start, regardless of whether they were initiated by a link click or a call to Turbo.visit.

Listen for the turbo:before-visit event to be notified when a visit is about to start, and use event.detail.url (or $event.originalEvent.detail.url, when using jQuery) to check the visit’s location. Then cancel the visit by calling event.preventDefault().

Restoration visits cannot be canceled and do not fire turbo:before-visit. Turbo Drive issues restoration visits in response to history navigation that has already taken place, typically via the browser’s Back or Forward buttons.
应用程序访问可以在开始之前取消,无论是通过单击链接还是调用Turbo.visit启动的。
倾听turbo:before访问事件,在访问即将开始时通知该事件,并使用event.detail。url(或$event.originalEvent.detail.url,当使用jQuery时)来检查访问的位置。然后通过调用event.proventDefault()取消访问。
恢复访问不能取消,并且在访问之前不要启动turbo:。Turbo Drive针对已经发生的历史导航发出恢复访问,通常通过浏览器的后退或前进按钮。

Pausing Rendering 
Application can pause rendering and make additional preparation before it will be executed.

Listen for the turbo:before-render event to be notified when rendering is about to start, and pause it using event.preventDefault(). Once the preparation is done continue rendering by calling event.detail.resume().

An example use case is adding exit animation for visits:
应用程序可以暂停渲染并在执行之前进行其他准备。
在渲染即将开始时,监听要通知的turbo:before渲染事件,并使用event.proventDefault() 暂停该事件。准备完成后,通过调用event.detail.resume()继续渲染。
一个示例用例是为访问添加退出动画:
document.addEventListener('turbo:before-render', async (event) => {
  event.preventDefault()

  await animateOut()

  event.detail.resume()
})
Pausing Requests
Application can pause request and make additional preparation before it will be executed.

Listen for the turbo:before-fetch-request event to be notified when a request is about to start, and pause it using event.preventDefault(). Once the preparation is done continue request by calling event.detail.resume().

An example use case is setting Authorization header for the request:
应用程序可以暂停请求并在执行之前进行额外的准备。
当一个请求即将启动时,在fetch请求事件被通知之前,监听turbo:before,并使用event.proventDefault()暂停它。准备完成后,通过调用event.detail.resume()继续请求。
一个示例用例是为请求设置Authorization头

document.addEventListener('turbo:before-fetch-request', async (event) => {
  event.preventDefault()

  const token = await getSessionToken(window.app)
  event.detail.fetchOptions.headers['Authorization'] = `Bearer ${token}`

  event.detail.resume()
})
Performing Visits With a Different Method
By default, link clicks send a GET request to your server. But you can change this with data-turbo-method:
默认情况下,单击链接会向服务器发送GET请求。但您可以使用data turbo方法来改变这一点:
<a href="/articles/54" data-turbo-method="delete">Delete the article</a>
The link will get converted into a hidden form next to the a element in the DOM. This means that the link can’t appear inside another form, as you can’t have nested forms.

You should also consider that for accessibility reasons, it’s better to use actual forms and buttons for anything that’s not a GET.
链接将被转换为  隐藏表单。这意味着链接不能出现在另一个表单中,因为您不能有嵌套的表单。
您还应该考虑到,出于可访问性的原因,最好使用实际的表单和按钮来执行不是GET的任何操作。

Disabling Turbo Drive on Specific Links or Forms
Turbo Drive can be disabled on a per-element basis by annotating the element or any of its ancestors with data-turbo="false".
通过使用数据Turbo=“false”对元素或其任何祖先进行注释,可以按元素禁用Turbo Drive。

<a href="/" data-turbo="false">Disabled</a>

<form action="/messages" method="post" data-turbo="false">
  ...
</form>

<div data-turbo="false">
  <a href="/">Disabled</a>
  <form action="/messages" method="post">
    ...
  </form>
</div>
To reenable when an ancestor has opted out, use data-turbo="true":

<div data-turbo="false">
  <a href="/" data-turbo="true">Enabled</a>
</div>
Links or forms with Turbo Drive disabled will be handled normally by the browser.

If you want Drive to be opt-in rather than opt-out, then you can set Turbo.session.drive = false; then, data-turbo="true" is used to enable Drive on a per-element basis. If you’re importing Turbo in a JavaScript pack, you can do this globally:
禁用Turbo Drive的链接或表单将由浏览器正常处理。
如果您希望Drive选择加入而不是退出,则可以设置Turbo.session.dive=false;然后,data turbo=“true” 用于在每个元素的基础上启用Drive。如果要在JavaScript包中导入Turbo,可以在全局范围内执行此操作:

import { Turbo } from "@hotwired/turbo-rails"
Turbo.session.drive = false
Displaying Progress
During Turbo Drive navigation, the browser will not display its native progress indicator. Turbo Drive installs a CSS-based progress bar to provide feedback while issuing a request.

The progress bar is enabled by default. It appears automatically for any page that takes longer than 500ms to load. (You can change this delay with the Turbo.setProgressBarDelay method.)

The progress bar is a <div> element with the class name turbo-progress-bar. Its default styles appear first in the document and can be overridden by rules that come later.

For example, the following CSS will result in a thick green progress bar:
在Turbo Drive导航期间,浏览器将不显示其本机进度指示器。Turbo Drive安装了一个基于CSS的进度条,以在发出请求时提供反馈。
默认情况下,进度条处于启用状态。对于加载时间超过500ms的任何页面,它都会自动显示。(您可以使用Turbo.setProgressBarDelay方法更改此延迟。)
进度条是一个<div>元素,类名为turbo进度条。它的默认样式首先出现在文档中,并且可以被后面的规则覆盖。
例如,以下CSS将生成一个粗绿色进度条:

.turbo-progress-bar {
  height: 5px;
  background-color: green;
}
To disable the progress bar entirely, set its visibility style to hidden:
要完全禁用进度条,请将其可见性样式设置为隐藏:
.turbo-progress-bar {
  visibility: hidden;
}
In tandem with the progress bar, Turbo Drive will also toggle the [aria-busy] attribute on the page’s <html> element during page navigations started from Visits or Form Submissions. Turbo Drive will set [aria-busy="true"] when the navigation begins, and will remove the [aria-busy] attribute when the navigation completes.
与进度条一起,Turbo Drive还将在从“访问”或“表单提交”开始的页面导航过程中切换页面<html>元素上的[aria busy]属性。
Turbo Drive将在导航开始时设置[aria busy=“true”],并在导航完成时删除[aria-busy]属性。

Reloading When Assets Change
Turbo Drive can track the URLs of asset elements in <head> from one page to the next and automatically issue a full reload if they change. This ensures that users always have the latest versions of your application’s scripts and styles.

Annotate asset elements with data-turbo-track="reload" and include a version identifier in your asset URLs. The identifier could be a number, a last-modified timestamp, or better, a digest of the asset’s contents, as in the following example.
Turbo Drive可以跟踪<head>中资产元素的URL,从一个页面到下一个页面,并在它们发生更改时自动发出完全重新加载。这确保用户始终拥有应用程序脚本和样式的最新版本。
使用data turbo track=“reload”标注asset elements,并在资产URL中包含版本标识符。标识符可以是一个数字、上次修改的时间戳,或者更好的是资产内容的摘要,如下面的示例所示。

<head>
  ...
  <link rel="stylesheet" href="/application-258e88d.css" data-turbo-track="reload">
  <script src="/application-cbd3cd4.js" data-turbo-track="reload"></script>
</head>
Ensuring Specific Pages Trigger a Full Reload
You can ensure visits to a certain page will always trigger a full reload by including a <meta name="turbo-visit-control"> element in the page’s <head>.
通过在页面的<head>中包含<meta name=“turbo visit control”>元素,您可以确保对某个页面的访问始终会触发完全重新加载
<head>
  ...
  <meta name="turbo-visit-control" content="reload">
</head>
This setting may be useful as a workaround for third-party JavaScript libraries that don’t interact well with Turbo Drive page changes.
对于与Turbo Drive页面更改交互不好的第三方JavaScript库,此设置可能很有用。

Setting a Root Location
协议+域名+端口 +(root location)=》  定义作用域。
By default, Turbo Drive only loads URLs with the same origin—i.e. the same protocol, domain name, and port—as the current document. A visit to any other URL falls back to a full page load.

In some cases, you may want to further scope Turbo Drive to a path on the same origin. For example, if your Turbo Drive application lives at /app, and the non-Turbo Drive help site lives at /help, links from the app to the help site shouldn’t use Turbo Drive.

Include a <meta name="turbo-root"> element in your pages’ <head> to scope Turbo Drive to a particular root location. Turbo Drive will only load same-origin URLs that are prefixed with this path.
默认情况下,Turbo Drive只加载与当前文档具有相同源代码的URL,即相同的协议、域名和端口。对任何其他URL的访问都会返回到完整页面加载。
在某些情况下,您可能需要将Turbo Drive的范围进一步扩大到同一原点上的路径。例如,如果您的Turbo Drive应用程序位于/app,而非Turbo Drive帮助站点位于/help,则从应用程序到帮助站点的链接不应使用Turbo Drive。
在页面的<head>中包含<meta name=“turbo root”>元素,以将turbo Drive扩展到特定的根位置。Turbo Drive将只加载带有此路径前缀的相同源URL。

<head>
  ...
  <meta name="turbo-root" content="/app">
</head>
Form Submissions
Turbo Drive handles form submissions in a manner similar to link clicks. The key difference is that form submissions can issue stateful requests using the HTTP POST method, while link clicks only ever issue stateless HTTP GET requests.
Throughout a submission, Turbo Drive will dispatch a series of events that target the <form> element and bubble up through the document:
Turbo Drive以类似于链接点击的方式处理表单提交。关键的区别是表单提交可以使用HTTP  POST方法发出有状态请求,而链接点击只会发出无状态的HTTP  GET请求。
在整个提交过程中,Turbo Drive将发送一系列针对<form>元素的事件,并在文档中冒泡:
开始-请求前-响应返回前-结束
  1. turbo:submit-start
  2. turbo:before-fetch-request
  3. turbo:before-fetch-response
  4. turbo:submit-end

During a submission, Turbo Drive will set the “submitter” element’s disabled attribute when the submission begins,then remove the attribute after the submission ends.
When submitting a <form> element, browser’s will treat the <input type="submit"> or <button> element that initiated the submission as the submitter.
To submit a <form> element programmatically, invoke the HTMLFormElement.requestSubmit() method and pass an <input type="submit"> or <button> element as an optional parameter.
在提交过程中,Turbo Drive将在提交开始时设置“提交者”元素的禁用属性,然后在提交结束后删除该属性。
当提交<form>元素时,浏览器会将发起提交的<input type=“submit”>或<button>元素视为提交者submitter
要以编程方式提交<form>元素,请调用HTMLFormElement。requestSubmit()方法,并将<input type=“submit”>或<button>元素作为可选参数传递。

If there are other changes you’d like to make during a <form> submission (for example, disabling all fields within a submitted <form>), you can declare your own event listeners:
如果您想在<form>提交期间进行其他更改(例如,禁用提交的<form>中的所有字段),您可以声明自己的事件监听器:
提交期间不能改:
addEventListener("turbo:submit-start", ({ target }) => {
  for (const field of target.elements) {
    field.disabled = true
  }
})
Redirecting After a Form Submission
提交后的重定向
After a stateful request from a form submission, Turbo Drive expects the server to return an HTTP 303 redirect response, which it will then follow and use to navigate and update the page without reloading.

The exception to this rule is when the response is rendered with either a 4xx or 5xx status code. This allows form validation errors to be rendered by having the server respond with 422 Unprocessable Entity and a broken server to display a “Something Went Wrong” screen on a 500 Internal Server Error.

The reason Turbo doesn’t allow regular rendering on 200’s from POST requests is that browsers have built-in behavior for dealing with reloads on POST visits where they present a “Are you sure you want to submit this form again?” dialogue that Turbo can’t replicate. Instead, Turbo will stay on the current URL upon a form submission that tries to render, rather than change it to the form action, since a reload would then issue a GET against that action URL, which may not even exist.

If the form submission is a GET request, you may render the directly rendered response by giving the form a data-turbo-frame target. If you’d like the URL to update as part of the rendering also pass a data-turbo-action attribute.
在表单提交的有状态请求后,Turbo Drive希望服务器返回HTTP 303重定向响应,然后它将跟踪该响应并使用该响应导航和更新页面,而无需重新加载。
此规则的例外情况是,当响应以4xx或5xx状态代码呈现时。这允许通过让服务器以422不可处理实体进行响应,并让损坏的服务器在500内部服务器错误上显示“Something Went Wrong”屏幕来呈现表单验证错误。

Turbo不允许通过POST请求在200上进行常规渲染的原因是,浏览器具有处理POST访问时重新加载的内置行为,当浏览器显示“您确定要再次提交此表单吗?”Turbo无法复制的对话。相反,Turbo将在试图呈现的表单提交时保留当前URL,而不是将其更改为表单操作,因为重新加载会针对该操作URL发出GET,而该操作URL可能根本不存在。
如果表单提交是一个GET请求,您可以通过给表单一个数据涡轮帧目标来呈现直接呈现的响应。如果您希望在渲染过程中更新URL,还可以传递一个data turbo动作属性。

Streaming After a Form Submission
Servers may also respond to form submissions with a Turbo Streams message by sending the header Content-Type: text/vnd.turbo-stream.html followed by one or more <turbo-stream> elements in the response body. This lets you update multiple parts of the page without navigating.

服务器还可以通过发送header Content-Type:text/vnd.Turbo-stream.html 来使用Turbo Streams消息响应 表单提交,然后是响应正文中的一个或多个<turbo-stream>元素。
这使您无需导航即可更新页面的多个部分

Preload Links Into the Cache 预加载到缓存中
Preload links into Turbo Drive’s cache using <a href="/" data-turbo-preload>Home</a>.

This will make page transitions feel lightning fast by providing a preview of a page even before the first visit. Use it to preload the most important pages in your application. Avoid over usage, as it will lead to loading content that is not needed.

It also dovetails nicely with pages that leverage Eager-Loading Frames or Lazy-Loading Frames. As you can preload the structure of the page and show the user a meaningful loading state while the interesting content loads.
使用<a href=“/”data Turbo Preload>Home</a>将链接预加载到Turbo Drive的缓存中。
即使在第一次访问之前,也可以提供页面预览,这将使页面转换感觉像闪电一样快。使用它来预加载应用程序中最重要的页面。避免过度使用,因为这会导致加载不需要的内容。
它还与利用“急加载帧”或“懒加载帧”的页面完美契合。因为您可以预加载页面的结构,并在加载感兴趣的内容时向用户显示有意义的加载状态

阅读量: 680
发布于:
修改于: