Навигация с Turbo Drive - geroi/turbo-rails GitHub Wiki

Навигация с помощью Turbo Drive

Turbo Drive - это часть Turbo, которая улучшает навигацию на уровне страницы. Она следит за кликами по ссылкам и отправкой форм, выполняет их в фоновом режиме и обновляет страницу без полной перезагрузки. Это эволюция библиотеки, ранее известной как Turbolinks.

Turbo Drive моделирует навигацию по странице как посещение (URL) с экшном.

Посещения представляют собой весь жизненный цикл навигации от щелчка до рендеринга. Сюда входит изменение истории браузера, отправка сетевого запроса, восстановление копии страницы из кэша, рендеринг окончательного ответа и обновление позиции прокрутки. Существует два типа визита: application визит, действие которого заключается в advance или replace, и визит restoration, действие которого заключается в restore.

Application визит инициируется нажатием на ссылку с поддержкой Turbo Drive или программным вызовом Turbo.visit(location). При application визите всегда отправляется сетевой запрос. Когда приходит ответ, Turbo Drive отображает его HTML и завершает визит.

Если это возможно, Turbo Drive выводит предварительный просмотр страницы из кэша сразу после начала посещения. Это улучшает воспринимаемую скорость при частой навигации между одними и теми же страницами.

Если местоположение визита включает анкор, Turbo Drive попытается прокрутить страницу до элемента с анкором. В противном случае он будет прокручивать страницу до самого верха.

Application visit приводит к изменению истории браузера; экшн визита определяет, каким образом.

Действие посещения по умолчанию - advance. Во время advance посещения Turbo Drive помещает новую запись в стек истории браузера с помощью history.pushState.

Приложения, использующие адаптер Turbo Drive iOS, обычно обрабатывают advance визиты путем размещения нового контроллера представления в стеке навигации. Аналогично, приложения, использующие адаптер Android, обычно размещают новую activity в стеке back.

Вы можете захотеть посетить местоположение без занесения новой записи истории в стек. Действие replace visit использует history.replaceState для отбрасывания самой верхней записи истории и замены ее новым местоположением.

Чтобы указать, что переход по ссылке должен вызвать посещение с заменой, аннотируйте ссылку с data-turbo-action="replace":

< a href="/edit" data-turbo-action="replace"> Редактировать</a>

Чтобы программно посетить местоположение с помощью действия replace, передайте action: "replace" в Turbo.visit:

Turbo. visit("/edit", { action: "replace" })

Приложения, использующие адаптер Turbo Drive iOS, обычно обрабатывают замену посещений путем dismiss самого верхнего контроллера представления и перемещения нового контроллера представления в стек навигации без анимации.

Turbo Drive автоматически инициирует посещение restoration при навигации с помощью кнопок "Назад" или "Вперед" браузера. Приложения, использующие адаптеры для iOS или Android, инициируют посещение восстановления при перемещении назад в навигационном стеке.

Если это возможно, Turbo Drive отрендерит копию страницы из кэша без запроса. В противном случае он получит свежую копию страницы по сети. Дополнительные сведения см. в разделе Понимание кэширования.

Turbo Drive сохраняет положение прокрутки каждой страницы перед переходом на другую страницу и автоматически возвращается к этому сохраненному положению при повторных посещениях.

Визиты restoration имеют экшн restoration, и Turbo Drive резервирует их для внутреннего использования. Вы не должны пытаться аннотировать ссылки или вызывать Turbo.visit с действием restore.

Посещения приложения могут быть отменены до их начала, независимо от того, были ли они инициированы щелчком по ссылке или вызовом Turbo.visit.

Ожидайте событие turbo:before-visit, чтобы получить уведомление о начале визита, и используйте event.detail.url (или $event.originalEvent.detail.url, если используется jQuery) для проверки местоположения визита. Затем отмените посещение, вызвав event.preventDefault().

Restoration визиты не могут быть отменены и не отменяют turbo:before-visit. Turbo Drive выполняет restoration визиты в ответ на уже состоявшуюся навигацию по истории, обычно с помощью кнопок "Назад" или "Вперед" браузера.

Приложение может приостановить рендеринг и провести дополнительную подготовку перед его выполнением. Слушайте событие turbo:before-render, чтобы получить уведомление, когда рендеринг вот-вот начнется, и приостановите его с помощью event.preventDefault(). После завершения подготовки продолжите рендеринг, вызвав event.detail.resume(). В качестве примера можно привести добавление анимации при выходе с сайта:

document. addEventListener('turbo:before-render', async (event) => {
    event.preventDefault()
    await animateOut()
    event.detail.resume()
})

Приложение может приостановить запрос и провести дополнительную подготовку перед его исполнением.

Слушайте событие turbo:before-fetch-request, чтобы получить уведомление, когда запрос вот-вот начнется, и приостановите его с помощью event.preventDefault(). После завершения подготовки запрос будет продолжен вызовом 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()
})

Turbo Drive можно отключить для каждого элемента, указав в аннотации элемента или любого из его предков data-turbo="false".

    <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>

Для повторного включения, если предок отказался, используйте data-turbo="true":

<div data-turbo="false">
  <a href="/" data-turbo="true">Enabled</a>
</div>

Ссылки или формы с отключенным Turbo Drive будут обрабатываться браузером в обычном режиме. Если вы хотите, чтобы Drive был опциональным, а не опциональным, вы можете установить Turbo.session.drive = false; тогда data-turbo="true" будет использоваться для включения Drive на основе каждого элемента. Если вы импортируете Turbo в пакете JavaScript, вы можете сделать это глобально:

import { Turbo } from "@hotwired/turbo-rails"
Turbo.session.drive = false

Отображение прогресса

Во время навигации по Turbo Drive браузер не отображает встроенный индикатор прогресса. Turbo Drive устанавливает индикатор прогресса на основе CSS для обеспечения обратной связи при выдаче запроса.

Индикатор выполнения включен по умолчанию. Он появляется автоматически на любой странице, загрузка которой занимает более 500 мс. (Вы можете изменить эту задержку с помощью метода Turbo.setProgressBarDelay).

Прогресс бар - это элемент

с именем класса turbo-progress-bar. Его стили по умолчанию появляются первыми в документе и могут быть отменены правилами, которые появляются позже.

Например, следующий CSS приведет к появлению толстого зеленого индикатора выполнения:

.turbo-progress-bar {
  height: 5px;
  background-color: green;
}

Чтобы полностью отключить индикатор выполнения, установите стиль его видимости на скрытый:

.turbo-progress-bar {
  visibility: hidden;
}

Turbo Drive может отслеживать URL-адреса элементов активов в <head> от одной страницы к другой и автоматически выполнять полную перезагрузку при их изменении. Это гарантирует, что пользователи всегда будут иметь последние версии скриптов и стилей вашего приложения.

Пометьте элементы активов параметром data-turbo-track="reload" и включите идентификатор версии в URL-адреса активов. Идентификатор может быть числом, временной меткой последнего изменения или, лучше, дайджестом содержимого актива, как в следующем примере. < голова

<head>
  ...
  <link rel="stylesheet" href="/application-258e88d.css" data-turbo-track="reload">
  <script src="/application-cbd3cd4.js" data-turbo-track="reload"></script>
</head>

Вы можете гарантировать, что посещение определенной страницы всегда будет вызывать полную перезагрузку, включив элемент <meta name="turbo-visit-control"> в <head> страницы.

<head>
  ...
  <meta name="turbo-visit-control" content="reload">
</head>

Эта настройка может быть полезна в качестве обходного пути для библиотек JavaScript сторонних разработчиков, которые плохо взаимодействуют с изменениями страниц Turbo Drive.

По умолчанию Turbo Drive загружает только URL с тем же происхождением - т.е. с тем же протоколом, доменным именем и портом - что и текущий документ. При посещении любого другого URL происходит возврат к полной загрузке страницы. В некоторых случаях вы можете захотеть дополнительно ограничить Turbo Drive путями того же происхождения. Например, если ваше приложение Turbo Drive находится по адресу /app, а сайт справки без Turbo Drive находится по адресу /help, ссылки из приложения на сайт справки не должны использовать Turbo Drive. Включите элемент <meta name="turbo-root"> в <head> ваших страниц, чтобы привязать Turbo Drive к определенному корневому расположению. Turbo Drive будет загружать только URL-адреса одного происхождения с префиксом этого пути.

<head>
  ...
  <meta name="turbo-root" content="/app">
</head>

Turbo Drive обрабатывает отправку форм так же, как и переходы по ссылкам. Ключевое отличие заключается в том, что формы могут отправлять запросы с указанием состояния, используя метод HTTP POST, в то время как клики по ссылкам отправляют только запросы HTTP GET без указания состояния.

После выполнения запроса с состоянием от отправки формы, Turbo Drive ожидает, что сервер вернет ответ HTTP 303 redirect, который он затем будет отслеживать и использовать для навигации и обновления страницы без перезагрузки. Исключением из этого правила является случай, когда ответ отображается с кодом состояния 4xx или 5xx. Это позволяет выводить ошибки валидации формы, заставляя сервер отвечать 422 Unprocessable Entity, а сломанный сервер выводить экран Something Went Wrong при 500 Internal Server Error.

Причина, по которой Turbo не позволяет обычный рендеринг на 200, заключается в том, что браузеры имеют встроенное поведение для работы с перезагрузкой при POST-посещении, где они представляют диалог "Вы уверены, что хотите отправить эту форму снова?", который Turbo не может воспроизвести. Вместо этого Turbo сохраняет текущий URL при отправке формы, которая пытается отобразиться, а не меняет его на действие формы, поскольку при перезагрузке будет выдан GET на URL действия, который может даже не существовать.

Серверы также могут отвечать на отправку формы сообщением Turbo Streams, отправляя заголовок Content-Type: text/vnd.turbo-stream.html, за которым следует один или несколько элементов <turbo-stream> в теле ответа. Это позволяет обновлять несколько частей страницы без навигации.

⚠️ **GitHub.com Fallback** ⚠️