Decompose with Turbo Frames


Turbo Frames allow predefined parts of a page to be updated on request. Any links and forms inside a frame are captured, and the frame contents automatically updated after receiving a response. Regardless of whether the server provides a full document, or just a fragment containing an updated version of the requested frame, only that particular frame will be extracted from the response to replace the existing content.
Turbo Frames 允许预先定义一个页面,用来响应请求。
任何链接和表单包含一个frame,就会被捕获。 这个Frame的内容在接到响应内容后会自动更新。
无论服务器是否提供一个完整的document ,还是提供包含要更新的部分内容,都只会从响应的内容里面提取特定的particular内容替换现存的内容。

Frames are created by wrapping a segment of the page in a <turbo-frame> element. Each element must have a unique ID, which is used to match the content being replaced when requesting new pages from the server. A single page can have multiple frames, each establishing their own context:
Frames被创建通过将部分页面封装在<turbo-frame>元素里面。
每个元素必须有个 唯一的ID,用于请求的新页面用来替换现有内容。
一个单页可以有多个frames, 各自有自己的上下文。


<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>
This page has two frames: One to display the message itself, with a link to edit it. One to list all the comments, with a form to add another. Each create their own context for navigation, capturing both links and submitting forms.
这个页面有2个frames,一个显示message, 里面有个edit的link,
一个是comments的列表,有个form用于增加。
每个有自己的上下文用于导航,抓取个字的链接和提交forms。


When the link to edit the message is clicked, the response provided by /messages/1/edit has its <turbo-frame id="message_1"> segment extracted, and the content replaces the frame from where the click originated. The edit response might look like this:
当这个编辑的链接被点击时,这个响应提供 /messages/1/edit 有它的 <turbo-frame id="message_1"> ,这段内容会替换掉你点击的frame。
编辑响应的内容就像下面这样:


<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>
Notice how the <h1> isn’t inside the <turbo-frame>. This means it’ll be ignored when the form replaces the display of the message upon editing. Only content inside a matching <turbo-frame> is used when the frame is updated.
注意:h1不在<turbo-frame>里面.
这意味着,当消息显示编辑的时候,用这个form替换的时候<h1>会被忽略.
仅仅是内容包含在一个匹配的<turbo-frame> 被用,当这个frame更新的时候。


Thus your page can easily play dual purposes: Make edits in place within a frame or edits outside of a frame where the entire page is dedicated to the action.
因此,您的页面可以轻松地实现双重目的:在框架内进行就地编辑,或在整个页面专用于该操作的框架外进行编辑。
也就是这个页面可以独立使用,也可以给turbo frame使用。


Eager-Loading Frames
Eager-loading Frames
急加载Frames

Frames don’t have to be populated when the page that contains them is loaded. If a src attribute is present on the turbo-frame tag, the referenced URL will automatically be loaded as soon as the tag appears on the page:
Frames不是必须populated,当页面包含的他们被加载。
如果 src attribute存在 turbo-frame上,这个引用的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>
This page lists all the emails available in your imbox immediately upon loading the page, but then makes two subsequent requests to present small trays at the bottom of the page for emails that have been set aside or are waiting for a later reply. These trays are created out of separate HTTP requests made to the URLs referenced in the src.

此页面在加载页面后立即列出您的邮箱中可用的所有电子邮件,但随后会提出两个请求,在页面底部显示已搁置或等待稍后回复的电子邮件的小托盘。这些托盘是根据对src中引用的URL发出的单独HTTP请求创建的。

In the example above, the trays start empty, but it’s also possible to populate the eager-loading frames with initial content, which is then overwritten when the content is fetched from the src:
托盘开始是空的,也可以初始化点内容填充eager-loading frames, 之后会被从src抓取来的内容覆盖。

<turbo-frame id="set_aside_tray" src="/emails/set_aside">
  <img src="/icons/spinner.gif">
</turbo-frame>
Upon loading the imbox page, the set-aside tray is loaded from /emails/set_aside, and the response must contain a corresponding <turbo-frame id="set_aside_tray"> element as in the original example:
当加载imbox页面是,放一边的tray已经被通过/email/set_aside 加载了. 这个响应必须包含一个corresponding <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>
This page now works in both its minimized form, where only the div with the individual emails are loaded into the tray frame on the imbox page, but also as a direct destination where a header and a description is provided. Just like in the example with the edit message form.
这个页面

Note that the <turbo-frame> on /emails/set_aside does not contain a src attribute. That attribute is only added to the frame that needs to lazily load the content, not to the rendered frame that provides the content.
注意 src属性只用着需要lazily load的content

During navigation, a Frame will set [aria-busy="true"] on the <turbo-frame> element when fetching the new contents. When the navigation completes, the Frame will remove the [aria-busy] attribute. When navigating the <turbo-frame> through a <form> submission, Turbo will toggle the [aria-busy="true"] attribute in tandem with the Frame’s.
在导航期间,Frame会设置一个 [aria-busy="true"] 在 <turbo-frame>元素,当fetching 新的内容时候。
当navigation完成,这个frame将会移除[aria-busy]属性。
当通过<form>提交导航,<turbo-frame>, turbo将与frame一起切换〔aria busy=“true”〕属性。

After navigation finishes, a Frame will set the [complete] attribute on the <turbo-frame> element.

Lazy-Loading Frames

Frames that aren’t visible when the page is first loaded can be marked with loading="lazy" such that they don’t start loading until they become visible. This works exactly like the lazy=true attribute on img. It’s a great way to delay loading of frames that sit inside summary/detail pairs or modals or anything else that starts out hidden and is then revealed.
第一次加载页面时不可见的框架可以标记为loading=“lazy”,这样直到它们变得可见才开始加载。这与img上的lazy=true属性完全相同。这是一个很好的方式来延迟加载位于摘要/细节对或模式或任何其他开始隐藏然后显示的帧。

Cache Benefits to Loading Frames

Turning page segments into frames can help make the page simpler to implement, but an equally important reason for doing this is to improve cache dynamics. Complex pages with many segments are hard to cache efficiently, especially if they mix content shared by many with content specialized for an individual user. The more segments, the more dependent keys required for the cache look-up, the more frequently the cache will churn.

Frames are ideal for separating segments that change on different timescales and for different audiences. Sometimes it makes sense to turn the per-user element of a page into a frame, if the bulk of the rest of the page is then easily shared across all users. Other times, it makes sense to do the opposite, where a heavily personalized page turns the one shared segment into a frame to serve it from a shared cache.

While the overhead of fetching loading frames is generally very low, you should still be judicious in just how many you load, especially if these frames would create load-in jitter on the page. Frames are, however, essentially free if the content isn’t immediately visible upon loading the page. Either because they’re hidden behind modals or below the fold.
将页面段转换为帧有助于使页面更易于实现,但这样做的一个同样重要的原因是改善缓存动态性。具有许多分段的复杂页面很难高效缓存,尤其是当它们将许多用户共享的内容与专门针对单个用户的内容混合在一起时。段越多,缓存查找所需的依赖键就越多,缓存搅动的频率就越高。
框架是分离在不同时间尺度上变化的片段和不同受众的理想选择。有时将页面的每个用户元素转换为一个框架是有意义的,如果页面的其余部分很容易在所有用户之间共享。其他时候,做相反的事情是有意义的,即一个高度个性化的页面将一个共享段变成一个帧,从共享缓存中为其提供服务。
虽然获取加载帧的开销通常很低,但您仍然应该谨慎地确定加载的帧数,尤其是如果这些帧会在页面上产生抖动负载。然而,如果加载页面时内容不能立即显示,则框架基本上是免费的。要么因为它们隐藏在模态后面,要么隐藏在褶皱下面。

Targeting Navigation Into or Out of a Frame

By default, navigation within a frame will target just that frame. This is true for both following links and submitting forms. But navigation can drive the entire page instead of the enclosing frame by setting the target to _top. Or it can drive another named frame by setting the target to the ID of that frame.
默认情况下,一个frame里的导航目标就是那个frame。
对于调整链接和提交forms表单,都是这样。
但是导航 可以drive整个页面,而不仅仅是enclosing frame, 这需要设置target='_top'.  或者它可以 drive 另一个 named frame 通过设置targe=另外frame的ID

In the example with the set-aside tray, the links within the tray point to individual emails. You don’t want those links to look for frame tags that match the set_aside_tray ID. You want to navigate directly to that email. This is done by marking the tray frames with the target attribute:
这个set-aside-tray的例子中, tray里面的链接指向各自的邮件。
你不想哪些链接去查找frame tags 匹配set_aside_tray ID.
你想去直接导航到email.
这通过设置tray frames的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>
Sometimes you want most links to operate within the frame context, but not others. This is also true of forms. You can add the data-turbo-frame attribute on non-frame elements to control this:
有时候你想most links去操作 在frame的上下文中,而不是其它的frames。对于forms确实是这样的。
你可以增加data-turbo-frame属性在没有 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">
    <a href="/messages/1/warning" data-turbo-frame="_self">
      Load warning within current frame
    </a>

    <input type="submit" value="Delete this message">
    (with a confirmation shown in a specific frame)
  </form>
</body>
Promoting a Frame Navigation to a Page Visit
将框架导航升级为页面访问

Navigating Frames provides applications with an opportunity to change part of the page’s contents while preserving the rest of the document’s state (for example, its current scroll position or focused element). There are times when we want changes to a Frame to also affect the browser’s history.
导航框架为应用程序提供了更改页面部分内容的机会,同时保留文档的其余状态(例如,当前滚动位置或焦点元素)。有时,我们希望对帧的更改也会影响浏览器的历史记录。

To promote a Frame navigation to a Visit, render the element with the [data-turbo-action] attribute. The attribute supports all Visit values, and can be declared on:
要将框架导航提升到就诊,请使用[data turbo action]属性渲染元素。该属性支持所有就诊值,可以在以下位置声明:

  • the <turbo-frame> element
  • any <a> elements that navigate the <turbo-frame>
  • any <form> elements that navigate the <turbo-frame>
  • any <input type="submit"> or <button> elements contained within <form> elements that navigate the <turbo-frame>
For example, consider a Frame that renders a paginated list of articles and transforms navigations into “advance” Actions:
例如,考虑一个框架,它呈现一个分页的文章列表,并将导航转换为“高级”操作:

<turbo-frame data-turbo-action="advance">
  <a href="/articles?page=2" rel="next">Next page</a>
</turbo-frame>
Clicking the <a rel="next"> element will set both the <turbo-frame> element’s [src] attribute and the browser’s path to /articles?page=2.
单击<a rel=“next”>元素将同时将<turbo frame>元素的[src]属性和浏览器的路径设置为/articles?第2页。

Note: when rendering the page after refreshing the browser, it is the application’s responsibility to render the second page of articles along with any other state derived from the URL path and search parameters.
注意:在刷新浏览器后呈现页面时,应用程序负责呈现文章的第二页以及从URL路径和搜索参数派生的任何其他状态。

Anti-Forgery Support (CSRF)

Turbo provides CSRF protection by checking the DOM for the existence of a <meta> tag with a name value of either csrf-param or csrf-token. For example:

<meta name="csrf-token" content="[your-token]">
Upon form submissions, the token will be automatically added to the request’s headers as X-CSRF-TOKEN. Requests made with data-turbo="false" will skip adding the token to headers.


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