Maison >interface Web >js tutoriel >Transitions fluides avec Turbo Streams

Transitions fluides avec Turbo Streams

DDD
DDDoriginal
2024-10-11 10:26:01521parcourir

Cet article a été initialement publié sur Rails Designer


Avec Turbo Streams, vous pouvez mettre à jour des parties spécifiques de votre application. Injectez un message de chat, mettez à jour une photo de profil ou insérez une alerte Le rapport est en cours de création.

La précision offerte par Turbo Streams est excellente. Mais souvent, la brusquerie des choses ne m'attire pas trop. Le nouveau composant est juste là (ou non, si vous le supprimez).

J'aimerais ajouter un peu plus de joie à mes applications et cette technique est exactement ce que fait. J'ai déjà exploré plusieurs techniques pour ajouter une sorte de transition ou d'animation lorsqu'un élément était inséré ou supprimé. Je l'ai peaufiné au fil des années tout en l'utilisant en production. Et je peux dire que je suis satisfait du fonctionnement de la technique que je décris aujourd'hui.

Tout d'abord, voici le résultat final :

Smooth Transitions with Turbo Streams

Et voici comment il est utilisé :

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

Si vous utilisez Rails Designer il est inclus pour vous et prêt à l'emploi. Gagnant! ?

Il y a pas mal d'éléments mobiles ici pour le faire démarrer, mais comme le montre l'exemple de code ci-dessus, l'utilisation est vraiment propre et personnalisable.

Commençons.

La première étape consiste à créer l'assistant turbo_stream_action_tag_with_block. Ceci est nécessaire, car l'assistant turbo_stream_action_tag disponible ne permet pas de transmettre un bloc (par exemple, render CollectionComponent) et les assistants Turbo stream Rails par défaut ne transmettent pas les attributs de données. Mais c'est assez simple :

# 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

La prochaine étape consiste à ajouter un écouteur pour turbo:before-stream-render et à ajouter un comportement personnalisé.

// 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")
}

Wow ! Cela a l'air effrayant ! Ce n'est vraiment pas trop mal ! Il intercepte l'événement turbo:before-stream-render, vérifiant l'ensemble de données de l'élément cible pour des attributs de transition spécifiques (par exemple data-transition-start). Pour saisir des éléments, il les définit comme masqués et ajoute un contrôleur de données apparaître. Pour quitter les éléments, il ajoute un contrôleur de données disparaître.

? Vous souhaitez être plus à l'aise pour écrire et comprendre JavaScript en tant que développeur Ruby on Rails ? Consultez le livre JavaScript pour les développeurs Rails

Assurez-vous de l'importer dans votre application.js.

 // app/javascript/application.js
 import "@hotwired/turbo-rails"
 import "./controllers"
 import "./utilities/turbo_stream_render.js"

 // …

Créons ces deux contrôleurs maintenant. Ils sont vraiment simples et s'appuient sur la superbe bibliothèque el-transition. Assurez-vous de l'ajouter à votre application (soit via NPM, soit 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()
    })
  }
}

Et une fois tout cela réglé, vous pouvez désormais ajouter des transitions fluides à tout élément ajouté ou supprimé à l'aide de flux turbo.

Ajoutez simplement quelques attributs de données (data : {transition_enter: ""}) au flux turbo et profitez d'une conduite en douceur.

Vous pouvez utiliser les mêmes attributs de données pris en charge par el-transition :

  • données-transition-enter;
  • data-transition-enter-start ;
  • data-transition-enter-end;
  • transition-données-congé ;
  • transition-données-leave-start ;
  • transition-données-congé-fin.

Pour ajouter des éléments :

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

Et pour supprimer des éléments :

<%= 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"} %>

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn