本文原刊於 Rails Designer
使用 Turbo Streams,您可以更新應用程式的特定部分。插入聊天訊息、更新個人資料圖片或插入正在建立報告警報。
Turbo Streams 提供的精確性非常好。但往往它的唐突,對我來說不太有吸引力。新組件就在那裡(或者如果您將其刪除,則不存在)。
我想為我的應用程式添加更多樂趣,而這項技術正是可以做到這一點。我之前探索了多種技術來在插入或刪除元素時添加某種過渡或動畫。多年來我在生產中使用它時對其進行了微調。我可以說我對我今天概述的技術的工作原理感到滿意。
首先,這將是最終結果:
使用方法如下:
<%= turbo_stream_action_tag_with_block "prepend", target: "resources", data: {transition_enter: "transition ease-in duration-300", transition_enter_start: "opacity-0", transition_enter_end: "opacity-100"} do %> <%= render ResourceComponent.new(resource: @resource) %> <% end %>
如果您正在使用 Rails Designer 它已包含,可供您使用。贏了! ?
這裡有相當多的移動元素來讓它運行,但從上面的程式碼範例中可以看出,用法非常乾淨且可自訂。
讓我們開始吧。
第一步是建立turbo_stream_action_tag_with_block 幫助器。這是必要的,因為可用的 Turbo_stream_action_tag 幫助程式不允許傳遞區塊(例如渲染 CollectionComponent),而且預設的 Turbo 流 Rails 幫助程式不會傳遞資料屬性。不過這很簡單:
# app/helpers/turbo_stream_helper.rb module TurboStreamHelper def turbo_stream_action_tag_with_block(action, target: nil, targets: nil, **options, &block) template_content = block_given? ? capture(&block) : nil turbo_stream_action_tag(action, target: target, targets: targets, template: template_content, **options) end end
下一步是為 Turbo:before-stream-render 新增監聽器並添加一些自訂行為。
// app/javascript/utilities/turbo_stream_render.js document.addEventListener("turbo:before-stream-render", (event) => { const { target } = event if (!(target.firstElementChild instanceof HTMLTemplateElement)) return const { dataset, templateElement } = target const { transitionEnter, transitionLeave } = dataset if (transitionEnter !== undefined) { transitionEnter(event, templateElement, dataset) } if (transitionLeave !== undefined) { handleTransitionLeave(event, target, dataset) } }) const handleTransitionEnter = (event, templateElement, dataset) => { event.preventDefault() const firstChild = templateElement.content.firstElementChild Object.assign(firstChild.dataset, dataset) firstChild.setAttribute("hidden", "") firstChild.setAttribute("data-controller", "appear") event.target.performAction() } const handleTransitionLeave = (event, target, dataset) => { const leaveElement = document.getElementById(target.target) if (!leaveElement) return event.preventDefault() Object.assign(leaveElement.dataset, dataset) leaveElement.setAttribute("data-controller", "disappear") }
哇!這看起來很嚇人!真的還不錯!它攔截turbo:before-stream-render事件,檢查目標元素的資料集的特定轉換屬性(例如data-transition-start)。對於輸入元素,它將它們設定為隱藏並添加一個 appear 資料控制器。為了離開元素,它增加了一個消失資料控制器。
?想要作為 Ruby on Rails 開發人員更輕鬆地編寫和理解 JavaScript?查看《JavaScript for Rails 開發人員》一書
確保將其匯入到您的application.js。
// app/javascript/application.js import "@hotwired/turbo-rails" import "./controllers" import "./utilities/turbo_stream_render.js" // …
現在讓我們來建立這兩個控制器。它們非常簡單,並且依賴很酷的 el-transition 庫。確保將其添加到您的應用程式中(透過 NPM 或 importmaps)。
// app/javascript/controllers/appear_controller.js import ApplicationController from "./application_controller" import { enter } from "el-transtion" export default class extends ApplicationController { connect() { enter(this.element) } }
// app/javascript/controllers/disappear_controller.js import ApplicationController from "./application_controller" import { leave } from "el-transtion" export default class extends ApplicationController { connect() { leave(this.element).then(() => { this.element.remove() }) } }
完成這一切後,您現在可以使用渦輪流為任何添加或刪除的元素添加平滑過渡。
只需將一些資料屬性(資料:{transition_enter: ""})附加到渦輪流中即可享受流暢的旅程。
您可以使用 el-transition 支援的相同資料屬性:
用於添加元素:
<%= turbo_stream_action_tag_with_block "prepend", target: "resources", data: {transition_enter: "transition ease-in duration-300", transition_enter_start: "opacity-0", transition_enter_end: "opacity-100"} do %> <%= render ResourceComponent.new(resource: @resource) %> <% end %>
刪除元素:
<%= turbo_stream_action_tag_with_block "remove", target: dom_id(@resource), data: {transition_leave: "transition ease-in duration-300", transition_leave_start: "opacity-100", transition_leave_end: "opacity-0"} %>
以上是透過 Turbo Streams 實現平滑過渡的詳細內容。更多資訊請關注PHP中文網其他相關文章!