Декомпозиция с помощью Turbo frames - geroi/turbo-rails GitHub Wiki

Turbo frames позволяют обновлять предопределенные части страницы по запросу. Любые ссылки и формы внутри фрейма захватываются, а содержимое фрейма автоматически обновляется после получения ответа. Независимо от того, предоставляет ли сервер полный документ или только фрагмент, содержащий обновленную версию запрашиваемого фрейма, из ответа будет извлечен только этот конкретный фрейм для замены существующего содержимого.

Фреймы создаются путем обертывания фрагмента страницы в элемент <turbo-frame>. Каждый элемент должен иметь уникальный идентификатор, который используется для сопоставления заменяемого содержимого при запросе новых страниц с сервера. На одной странице может быть несколько фреймов, каждый из которых создает свой собственный контекст:

<body>
  <div id="navigation">Links targeting the entire page</div>

  <turbo-frame id="message_1">
    <h1>My message title</h1>
    <p>My message content</p>
    <a href="/messages/1/edit">Edit this message</a>
  </turbo-frame>

  <turbo-frame id="comments">
    <div id="comment_1">One comment</div>
    <div id="comment_2">Two comments</div>

    <form action="/messages/comments">...</form>
  </turbo-frame>
</body>

Эта страница имеет два фрейма: Один для отображения самого сообщения со ссылкой для его редактирования. Один - для списка всех комментариев, с формой для добавления еще одного. Каждый из них создает свой собственный контекст для навигации, фиксируя как ссылки, так и формы отправки.

Когда нажимается ссылка для редактирования сообщения, из ответа, предоставленного /messages/1/edit, извлекается сегмент <turbo-frame id="message_1">, и содержимое заменяет фрейм, в котором произошел щелчок. Ответ на редактирование может выглядеть следующим образом:

<body>
  <h1>Editing message</h1>

  <turbo-frame id="message_1">
    <form action="/messages/1">
      <input name="message[name]" type="text" value="My message title">
      <textarea name="message[content]">My message content</textarea>
      <input type="submit">
    </form>
  </turbo-frame>
</body>

Обратите внимание, что <h1> не находится внутри . Это означает, что он будет проигнорирован, когда форма заменит отображение сообщения при редактировании. Только содержимое внутри соответствующего используется при обновлении фрейма.

Таким образом, ваша страница может легко играть двойную роль: Вносить правки на месте в рамке или вносить правки вне рамки, когда вся страница посвящена действию.

Ленивая загрузка фреймов

Фреймы не обязательно заполнять при загрузке содержащей их страницы. Если в теге turbo-frame присутствует атрибут src, то при появлении тега на странице автоматически загружается URL, на который ссылается фрейм:

<body>
  <h1>Imbox</h1>

  <div id="emails">
    ...
  </div>

  <turbo-frame id="set_aside_tray" src="/emails/set_aside">
  </turbo-frame>

  <turbo-frame id="reply_later_tray" src="/emails/reply_later">
  </turbo-frame>
</body>

Эта страница выводит список всех писем, имеющихся в вашем почтовом ящике, сразу после загрузки страницы, но затем делает два последующих запроса, чтобы представить небольшие треи в нижней части страницы для писем, которые были отложены или ожидают ответа позже. Эти треи создаются из отдельных HTTP-запросов к URL-адресам, указанным в src.

В приведенном выше примере лотки начинаются пустыми, но можно также заполнить лениво загружаемые фреймы начальным содержимым, которое затем перезаписывается, когда содержимое извлекается из src:

<turbo-frame id="set_aside_tray" src="/emails/set_aside">
  <img src="/icons/spinner.gif">
</turbo-frame>

При загрузке страницы imbox лоток set-aside загружается из /emails/set_aside, и ответ должен содержать соответствующий элемент <turbo-frame id="set_aside_tray">, как в исходном примере:

<body>
  <h1>Set Aside Emails</h1>

  <p>These are emails you've set aside</p>

  <turbo-frame id="set_aside_tray">
    <div id="emails">
      <div id="email_1">
        <a href="/emails/1">My important email</a>
      </div>
    </div>
  </turbo-frame>
</body>

Теперь эта страница работает как в свернутом виде, когда только div с отдельными письмами загружается во фрейм трея на странице imbox, так и в прямом виде, когда предоставляется заголовок и описание. Так же, как в примере с формой редактирования сообщения.

Обратите внимание, что <turbo-frame> на /emails/set_aside не содержит атрибута src. Этот атрибут добавляется только к фрейму, который должен лениво загрузить содержимое, а не к рендеринговому фрейму, который предоставляет содержимое.

Преимущества кэширования перед ленивой загрузкой фреймов

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

Фреймы идеально подходят для разделения сегментов, которые изменяются в разное время и для разных аудиторий. Иногда имеет смысл превратить элемент страницы, предназначенный для каждого пользователя, во фрейм, если большая часть остальной страницы затем будет легко доступна всем пользователям. В других случаях имеет смысл поступить наоборот, когда на сильно персонализированной странице один общий сегмент превращается во фрейм, чтобы обслуживать его из общего кэша.

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

Направление навигации в фрейм или за его пределы

По умолчанию навигация внутри фрейма будет нацелена только на этот фрейм. Это справедливо как для перехода по ссылкам, так и для отправки форм. Но навигация может управлять всей страницей вместо вложенного фрейма, установив цель на _top. Или она может управлять другим именованным фреймом, установив цель на id этого фрейма.

В примере с отведенным лотком ссылки внутри лотка указывают на отдельные электронные письма. Вы не хотите, чтобы эти ссылки искали теги фрейма, соответствующие идентификатору set_aside_tray. Вы хотите перейти непосредственно к этому письму. Это можно сделать, пометив рамки лотка атрибутом target:

<body>
  <h1>Imbox</h1>
  ...
  <turbo-frame id="set_aside_tray" src="/emails/set_aside" target="_top">
  </turbo-frame>
</body>

<body>
  <h1>Set Aside Emails</h1>
  ...
  <turbo-frame id="set_aside_tray" target="_top">
    ...
  </turbo-frame>
</body>

Иногда вы хотите, чтобы большинство ссылок работали в контексте фрейма, но не другие. Это также относится к формам. Для управления этим можно добавить атрибут data-turbo-frame для элементов без фрейма:

<body>
  <turbo-frame id="message_1">
    ...
    <a href="/messages/1/edit">
      Edit this message (within the current frame)
    </a>

    <a href="/messages/1/permission" data-turbo-frame="_top">
      Change permissions (replace the whole page)
    </a>
  </turbo-frame>

  <form action="/messages/1/delete" data-turbo-frame="message_1">
    <input type="submit" value="Delete this message">
    (with a confirmation shown in a specific frame)
  </form>
</body>
⚠️ **GitHub.com Fallback** ⚠️