Die Macht von benannten Übergängen in Vue

Avatar of Travis Almand
Travis Almand am

DigitalOcean bietet Cloud-Produkte für jede Phase Ihrer Reise. Starten Sie mit 200 $ kostenlosem Guthaben!

Vue bietet verschiedene Möglichkeiten, die visuelle Darstellung eines Elements oder einer Komponente beim Einfügen in das DOM zu steuern. Beispiele hierfür sind Einblenden, Einblenden oder andere visuelle Effekte. Fast die gesamte Funktionalität basiert auf einer einzigen Komponente: der Transition-Komponente.

Ein einfaches Beispiel hierfür ist ein einzelnes v-if, das auf einem booleschen Wert basiert. Wenn der boolesche Wert true ist, erscheint das Element. Wenn der boolesche Wert false ist, verschwindet das Element. Normalerweise würde dieses Element einfach aus dem Nichts auftauchen und verschwinden, aber mit der Transition-Komponente können Sie den visuellen Effekt steuern.

<transition>
  <div v-if="isVisible">is this visible?</div>
</transition>

Mehrere Artikel wurden bereits veröffentlicht, die die Transition-Komponente gut behandeln, wie z. B. Artikel von Sarah Drasner, Nicolas Udy und Hassan Djirdeh. Jeder Artikel behandelt verschiedene Aspekte der Vue Transition-Komponente im Detail. Dieser Artikel erweitert das Thema, indem er sich auf einen Aspekt der Transition-Komponente konzentriert; die Tatsache, dass sie "benannt" sein können.

<transition name="fade">
  <div v-if="isVisible">is this visible?</div>
</transition>

Die anfängliche Änderung, die dieses Attribut bietet, besteht darin, dass die CSS-Klassen, die während der Übergangssequenz auf das Element angewendet werden, mit dem angegebenen Namen präfigiert werden. Im Grunde wäre es fade-enter anstelle von v-enter aus dem obigen Beispiel. Dieses einzelne Attribut kann weit über diese einfache Option hinausgehen. Es kann verwendet werden, um bestimmte Funktionen von Vue und CSS zu nutzen, die interessante Ergebnisse ermöglichen.

Eine weitere zu berücksichtigende Sache ist, dass das Namensattribut gebunden werden kann

<transition v-bind:name="currentTransition">
  <div v-if="isVisible">is this visible?</div>
</transition>

In diesem Beispiel wird der Übergang nach dem Wert benannt, zu dem currentTransition aufgelöst wird. Diese einfache Änderung bietet eine weitere Ebene von Optionen und Funktionen für die Animationen einer App. Mit statischen und dynamischen benannten Übergängen kann ein Projekt eine Reihe von vordefinierten Übergängen haben, die in der gesamten App angewendet werden können, Komponenten, die bestehende Übergänge, die auf sie angewendet werden, erweitern können, den verwendeten Übergang vor oder nach der Anwendung wechseln können, Benutzern die Auswahl von Übergängen ermöglichen und steuern können, wie einzelne Elemente einer Liste basierend auf dem aktuellen Zustand dieser Liste in den Platz übergehen.

Dieser Artikel soll diese Funktionen untersuchen und erklären, wie sie verwendet werden.

Was passiert, wenn Übergänge benannt sind?

Standardmäßig, wenn eine Transition-Komponente verwendet wird, wendet sie bestimmte Klassen in einer bestimmten Reihenfolge auf das Element an. Diese Klassen können in CSS genutzt werden. Ohne CSS bewirken diese Klassen im Wesentlichen nichts für das Element. Daher besteht Bedarf an CSS dieser Art

.v-enter,
.v-leave-to {
  opacity: 0;
}

.v-enter-active,
.v-leave-active {
  transition: 0.5s;
}

Dies bewirkt, dass das Element mit einer Dauer von einer halben Sekunde ein- und ausgeblendet wird. Eine geringfügige Änderung am Übergang sorgt für eine elegante visuelle Rückmeldung an den Benutzer. Dennoch gibt es ein Problem zu bedenken. Aber zuerst, was ist anders bei einem benannten Übergang?

.fade-enter,
.fade-leave-to {
  opacity: 0;
}

.fade-enter-active,
.fade-leave-active {
  transition: 0.5s;
}

Im Wesentlichen das gleiche CSS, aber mit fade- als Präfix anstelle von v-. Diese Benennung adressiert das potenzielle Problem, das auftreten kann, wenn die Standardklassennamen der Transition-Komponente verwendet werden. Das v- Präfix macht die Klassen global wirksam, insbesondere wenn das CSS im Style-Block der Root-Ebene der App platziert ist. Dies würde in der Tat *alle* Übergänge ohne Namensattribut in der gesamten App denselben Übergangseffekt verwenden lassen. Für kleine Apps mag dies ausreichen, aber in größeren, komplexeren Apps kann es zu unerwünschten visuellen Effekten führen, da nicht alles über eine halbe Sekunde ein- und ausgeblendet werden sollte.

Die Benennung von Übergängen bietet Entwicklern ein Kontrollniveau für das gesamte Projekt, wie verschiedene Elemente oder Komponenten visuell eingefügt oder entfernt werden. Es wird empfohlen, alle Übergänge zu benennen – auch wenn es nur einen gibt –, um die Gewohnheit dafür zu etablieren. Selbst wenn eine App nur einen einzigen Übergangseffekt hat, kann es sein, dass zu einem späteren Zeitpunkt ein neuer hinzugefügt werden muss. Wenn bereits vorhandene Übergänge im Projekt benannt sind, erleichtert dies das Hinzufügen eines neuen.

Erstellung einer Sammlung von Transition-Effekten

Die Benennung von Übergängen ermöglicht einen einfachen und dennoch sehr nützlichen Prozess. Eine gängige Praxis könnte darin bestehen, die Übergangsklassen als Teil der Komponente zu erstellen, die sie verwendet. Wenn eine andere gängige Praxis zur Scoping von Stilen für eine Komponente durchgeführt wird, sind diese Klassen nur für diese spezielle Komponente verfügbar. Wenn zwei verschiedene Komponenten ähnliche Übergänge in ihren Stilblöcken haben, duplizieren wir nur Code.

Betrachten wir also, die CSS für Übergänge im Style-Block des Root der App zu belassen, typischerweise in der Datei app.vue. Für die meisten meiner Projekte platziere ich sie als letzten Abschnitt des Style-Blocks, wodurch sie leicht für Anpassungen und Ergänzungen zu finden sind. Die Beibehaltung des CSS an diesem Ort macht die Übergangseffekte für jede Verwendung der Transition-Komponente in der gesamten App verfügbar. Hier sind Beispiele aus einigen meiner Projekte.

.fade-enter,
.fade-leave-to { opacity: 0; }
.fade-enter-active,
.fade-leave-active { transition: 0.5s; }

.slide-enter {
  opacity: 0;
  transform: scale3d(2, 0.5, 1) translate3d(400px, 0, 0);
}

.slide-enter-to { transform: scale3d(1, 1, 1); }
.slide-enter-active,
.slide-leave-active { transition: 0.5s cubic-bezier(0.68, -0.55, 0.265, 1.55); }
.slide-leave { transform: scale3d(1, 1, 1); }

.slide-leave-to {
  opacity: 0;
  transform: scale3d(2, 0.5, 1) translate3d(-400px, 0, 0);
}

.rotate-enter { transform: perspective(500px) rotate3d(0, 1, 0, 90deg); }
.rotate-enter-active,
.rotate-leave-active { transition: 0.5s; }
.rotate-leave-to { transform: perspective(500px) rotate3d(0, 1, 0, -90deg); }

Es gibt mehrere Möglichkeiten, diese Übergangsklassen zu speichern, abhängig von Ihren Vorlieben und den Anforderungen des Projekts. Die erste, wie bereits erwähnt, besteht darin, alles im Style-Block der Datei app.vue zu belassen. Sie können auch eine Sass-Teildatei mit allen Übergängen im Assets-Ordner des Projekts führen und diese in den Style-Block der App importieren.

<style lang="scss">
  @import "assets/_transitions.scss";
</style>

Diese Methode ermöglicht Anpassungen und Ergänzungen der Übergangssammlung außerhalb der Vue-Dateien. Ein weiterer Vorteil dieses Setups ist, dass eine solche Datei leicht zwischen Projekten übertragen werden kann, wenn sie Übergangseffekte teilen. Wenn ein Projekt einen neuen Übergang erhält, ist es einfach genug, die Ergänzung auf ein anderes Projekt zu übertragen, ohne Hauptprojektdateien anfassen zu müssen.

Wenn Sie CSS anstelle von Sass verwenden, können Sie die Datei als Anforderung des Projekts einbeziehen. Dies können Sie erreichen, indem Sie die Datei im Assets-Ordner des Projekts belassen und eine require-Anweisung in der Datei main.js platzieren.

require("@/assets/transitions.css");

Eine weitere Option ist, die Übergangsstile in einer statischen CSS-Datei zu belassen, die woanders gespeichert werden kann, entweder im öffentlichen Ordner des Projekts oder einfach auf dem Server selbst. Da es sich um eine reguläre CSS-Datei handelt, ist kein Erstellen oder Bereitstellen erforderlich – fügen Sie einfach einen Linkverweis in die Datei index.html ein.

<link rel="stylesheet" type="text/css" href="/css/transitions.css">

Diese Datei könnte auch potenziell in einem CDN gespeichert werden, damit alle Projekte sie gemeinsam nutzen können. Wann immer die Datei aktualisiert wird, sind die Änderungen überall sofort verfügbar, wo sie referenziert wird. Wenn ein neuer Übergangsname erstellt wird, können bestehende Projekte den neuen Namen nach Bedarf verwenden.

Nun halten wir kurz inne

Während wir eine Sammlung von Übergängen für unser Projekt erstellen, sollten wir an Benutzer denken, die möglicherweise keine abrupten Animationen wünschen oder gar keine Animationen wünschen. Einige Leute könnten unsere Animationen als übertrieben und unnötig empfinden, aber für einige können sie tatsächlich Probleme verursachen. Vor einiger Zeit führte WebKit die Media Query prefers-reduced-motion ein, um mögliche Probleme mit dem Vestibular Spectrum Disorder zu unterstützen. Eric Bailey hat auch eine schöne Einführung zu dieser Media Query veröffentlicht.

In den meisten Fällen ist das Hinzufügen der Media Query als Teil unserer Sammlung von Übergängen recht einfach und sollte in Betracht gezogen werden. Wir können entweder die Animationsmenge reduzieren, um negative Effekte zu minimieren, oder sie einfach ausschalten.

Hier ist ein einfaches Beispiel aus einer meiner Demos unten

.next-enter {
  opacity: 0;
  transform: scale3d(2, 0.5, 1) translate3d(400px, 0, 0);
}

.next-enter-to { transform: scale3d(1, 1, 1); }
.next-enter-active,
.next-leave-active { transition: 0.5s cubic-bezier(0.68, -0.55, 0.265, 1.55); }
.next-leave { transform: scale3d(1, 1, 1); }

.next-leave-to {
  opacity: 0;
  transform: scale3d(2, 0.5, 1) translate3d(-400px, 0, 0);
}

/* If animations are reduced at the OS level, use simpler transitions */
@media screen and (prefers-reduced-motion: reduce) {
  .next-enter {
    opacity: 0;
    transform: translate3d(100px, 0, 0);
  }

  .next-enter-active,
  .next-leave-active { transition: 0.5s; }

  .next-leave-to {
    opacity: 0;
    transform: translate3d(-100px, 0, 0);
  }
}

In diesem Beispiel habe ich einen eher übertriebenen Übergang genommen und ihn einfacher gestaltet. Die Animation ist ein Schiebeeffekt nach links mit einer elastischen Ease, dann skaliert er herunter und blendet aus, während er sich entfernt. Wenn jemand die Einstellung "reduced motion" aktiviert hat, wird die Animation zu einem viel einfacheren Übergang mit kürzerer Distanz (was ihm eine langsamere Geschwindigkeit verleiht) und behält das Ausblenden bei. Wenn wir sie ausschalten wollten, müssten wir nur die Klassen mit der transition-Eigenschaft referenzieren und ihren Wert auf none setzen.

Zum Testen muss eine Checkbox auf Ihrem jeweiligen Betriebssystem gefunden und ausgewählt werden. Unter Windows finden Sie sie unter Systemsteuerung > Centro für Barrierefreiheit > Den Computer leichter bedienen; suchen Sie nach "Alle unnötigen Animationen deaktivieren (wenn möglich)". Unter Mac finden Sie sie unter Systemeinstellungen > Bedienungshilfen > Anzeige; suchen Sie nach "Bewegung reduzieren". Die neuesten iOS-Geräte haben eine ähnliche Einstellung unter Bedienungshilfen.

Bleiben wir flexibel mit unserer Transition-Sammlung

Mit dieser Sammlung von Übergängen gibt es die potenzielle Schwierigkeit mangelnder Flexibilität bei den Effekten. Was ist zum Beispiel, wenn ein Element eine etwas langsamere Überblendzeit benötigt? Nehmen wir an, alles andere im Effekt bleibt gleich, nur die transition-duration muss anders sein. Es gibt Möglichkeiten, dies zu berücksichtigen, ohne einen komplett neuen Übergangsnamen erstellen zu müssen.

Die einfachste Methode ist die Verwendung eines Inline-Stils direkt auf dem Element innerhalb der Transition-Komponente.

<transition name="fade">
  <div style="transition-duration: 6s;" v-if="isVisible">this has a different duration</div>
</transition>

Eine solche Änderung kann auch über die verschiedenen Möglichkeiten erfolgen, mit denen Vue Stile und Klassen handhabt.

Nehmen wir an, Sie verwenden das Komponenten-Element mit dem Attribut is für dynamische Komponenten wie diese

<transition name="fade" mode="out-in">
  <component :is="currentComponent"></component>
</transition>

Auch mit dieser dynamischen Komponente haben wir Optionen, Eigenschaften des Transition-Effekts anzupassen. Wiederum können wir einen Inline-Stil auf dem Komponenten-Element anwenden, der auf das Root-Element der Komponente angewendet wird. Das Root-Element erhält auch die Übergangsklassen, sodass wir deren Eigenschaften direkt überschreiben würden.

<transition name="fade" mode="out-in">
  <component :is="currentComponent" style="transition-duration: 6s;"></component>
</transition>

Eine weitere Option ist, Props an unsere Komponenten zu übergeben. Auf diese Weise können die gewünschten Änderungen über den Code der Komponente auf deren Root-Element angewendet werden.

<transition name="fade" mode="out-in">
  <component :is="currentComponent" duration="6s"></component>
</transition>
<template>
  <div :style="`transition-duration: ${duration}`">component one</div>
</template>

<script>
export default {
  name: "component-one",
  props: {
    duration: String
  }
};
</script>

Wir können auch die Eigenschaften der Übergangsklassen innerhalb des Style-Blocks der Komponente überschreiben, insbesondere wenn sie gescopt ist.

<style scoped>
  .fade-enter-active,
  .fade-leave-active { transition-duration: 1s; }
</style>

In diesem Fall hat die Komponente eine Fade-Dauer von einer Sekunde anstelle der globalen Dauer von einer halben Sekunde. Wir können sogar noch weiter gehen und unterschiedliche Dauern für jede Seite der Sequenz haben.

<style scoped>
  .fade-enter-active { transition-duration: 1s; }
  .fade-leave-active { transition-duration: 2s; }
</style>

Jede der globalen Übergangsklassen kann bei Bedarf innerhalb der Komponente geändert werden. Obwohl dies nicht ganz so flexibel ist wie die Änderung der Eigenschaft außerhalb einer Klassenstruktur, kann es unter bestimmten Umständen dennoch sehr nützlich sein.

Wie Sie sehen können, haben wir selbst mit unserer Sammlung von vorgefertigten Übergängen noch Optionen für Flexibilität.

Dynamische Übergänge

Selbst nach all diesen interessanten Dingen, die wir mit Vues Transition-Komponente tun können, wartet noch eine weitere interessante Funktion darauf, erkundet zu werden. Das name-Attribut der Transition-Komponente kann dynamisch sein, was bedeutet, dass wir die aktuelle Transition nach Belieben ändern können.

Das bedeutet, dass der Übergang so geändert werden kann, dass er verschiedene Animationseffekte mit verschiedenen Situationen hat, basierend auf Code. Zum Beispiel könnten wir einen Übergang ändern, weil die Antwort auf eine Frage, Übergänge, die durch Benutzerinteraktion entschieden werden, und eine Liste, die verschiedene Übergänge basierend auf dem aktuellen Zustand der Liste selbst verwendet.

Schauen wir uns diese drei Beispiele an.

Beispiel 1: Übergang basierend auf einer Antwort ändern

In diesem Beispiel haben wir eine einfache mathematische Frage, die beantwortet werden muss. Zwei Zahlen werden zufällig ausgewählt und wir sollen die Summe angeben. Dann wird der Button geklickt, um die Antwort mit der erwarteten Antwort zu vergleichen. Eine kleine Benachrichtigung erscheint über der Gleichung, die angibt, ob die Antwort richtig oder falsch ist. Wenn die Antwort korrekt ist, erhält die Benachrichtigung einen Übergang, der ein Kopfnicken mit einer Auf- und Ab-Animation suggeriert. Wenn Ihre Antwort falsch ist, bewegt sich die Benachrichtigung seitwärts, was ein Kopfschütteln suggeriert.

Sehen Sie den Pen
VueJS Dynamic Transitions: Change Transition Based on an Answer
von Travis Almand (@talmand)
auf CodePen.

Die Logik dahinter ist nicht übermäßig kompliziert, ebenso wenig wie die Einrichtung des Übergangs. Hier ist das HTML

<transition :name="currentTransition">
  <div id="notification" :class="response.toString()" v-if="answerChecked">{{ response }}</div>
</transition>

Ziemlich einfach gehalten. Wir haben einen gebundenen Namen für den Übergang und dann einen v-if auf dem Benachrichtigungs-Div. Wir wenden auch eine true oder false-Klasse an, um die Benachrichtigung basierend auf der Antwort zu dekorieren.

Hier ist das CSS für die Übergänge

.positive-enter-active { animation: positive 1s; }
@keyframes positive {
  0% { transform: translate3d(0, 0, 0); }
  25% { transform: translate3d(0, -20px, 0); }
  50% { transform: translate3d(0, 20px, 0); }
  75% { transform: translate3d(0, -20px, 0); }
  100% { transform: translate3d(0, 0, 0); }
}

.negative-enter-active { animation: negative 1s; }
@keyframes negative {
  0% { transform: translate3d(0, 0, 0); }
  25% { transform: translate3d(-20px, 0, 0); }
  50% { transform: translate3d(20px, 0, 0); }
  75% { transform: translate3d(-20px, 0, 0); }
  100% { transform: translate3d(0, 0, 0); }
}

Sie werden sehen, dass ich CSS-Animationen verwende, um die Auf-und-Ab- und Seitenbewegungs-Effekte zu erzielen.

Hier ist ein Teil des JavaScript

methods: {
  randomProblem: function () {
    this.a = Math.floor(Math.random() * Math.floor(10));
    this.b = Math.floor(Math.random() * Math.floor(10));
  },
  check: function () {
    this.response = this.a + this.b === parseInt(this.answer);
    this.answerChecked = true;
    this.currentTransition = this.response ? 'positive' : 'negative';
  },
  reset: function () {
    this.answer = null;
    this.answerChecked = false;
    this.randomProblem();
  }
}

Da ist die Methode randomProblem, die unsere Gleichung aufstellt. Die Methode check, die entscheidet, welcher Übergangseffekt verwendet werden soll, basierend auf dem Vergleich der eingegebenen Antwort mit der korrekten Antwort. Dann die einfache Methode reset, die einfach alles zurücksetzt.

Dies ist nur ein einfaches Beispiel. Ein weiteres mögliches Beispiel ist eine Benachrichtigung, die zwei verschiedene Effekte hat, je nachdem, ob die Benachrichtigung wichtig ist oder nicht. Wenn die Nachricht nicht übermäßig wichtig ist, können wir eine subtile Animation haben, die die Augen des Benutzers nicht von der aktuellen Aufgabe ablenkt. Wenn sie wichtig ist, könnten wir eine Animation verwenden, die direkter ist, um die Augen zur Benachrichtigung zu zwingen.

Beispiel 2: Übergang basierend auf Benutzerinteraktion ändern

Etwas anderes, das wir bauen können, ist eine Art Karussell. Dies könnten Präsentationsfolien, eine Bildergalerie oder eine Reihe von Anweisungen sein. Die Grundidee ist, dass wir dem Benutzer Informationen in einer Sequenz präsentieren müssen. Bei dieser Präsentation entscheidet der Benutzer, wann er fortfahren und ob er vorwärts oder rückwärts gehen möchte.

Sehen Sie den Pen
VueJS Dynamic Transitions: Change Transition Based on User Interaction
von Travis Almand (@talmand)
auf CodePen.

Auch dies ist wieder eine eher einfache Einrichtung. Das Beispiel ist mehr oder weniger eine Art Folienpräsentation. Die beiden Schaltflächen unten wechseln zwischen zwei Komponenten mit einem Schiebeübergang. Ein echtes Projekt hätte mehr Komponenten oder vielleicht Logik, um den Inhalt der Komponenten basierend auf der aktuellen Folie zu ändern. Dieses Beispiel bleibt einfach, um die Idee zu demonstrieren.

Hier ist das HTML

<transition :name="currentTransition" mode="out-in">
  <component :is="slides[currentSlide]"></component>
</transition>

Sie werden sehen, dass wir lediglich einen Übergang durchführen, wenn die Komponente durch ein gebundenes is-Attribut auf dem Komponenten-Element ausgetauscht wird.

Hier ist das CSS

.next-enter {
  opacity: 0;
  transform: scale3d(2, 0.5, 1) translate3d(400px, 0, 0);
}

.next-enter-to { transform: scale3d(1, 1, 1); }
.next-enter-active,
.next-leave-active { transition: 0.5s cubic-bezier(0.68, -0.55, 0.265, 1.55); }
.next-leave { transform: scale3d(1, 1, 1); }

.next-leave-to {
  opacity: 0;
  transform: scale3d(2, 0.5, 1) translate3d(-400px, 0, 0);
}

.prev-enter {
  opacity: 0;
  transform: scale3d(2, 0.5, 1) translate3d(-400px, 0, 0);
}

.prev-enter-to { transform: scale3d(1, 1, 1); }
.prev-enter-active,
.prev-leave-active { transition: 0.5s cubic-bezier(0.68, -0.55, 0.265, 1.55); }
.prev-leave { transform: scale3d(1, 1, 1); }

.prev-leave-to {
  opacity: 0;
  transform: scale3d(2, 0.5, 1) translate3d(400px, 0, 0);
}

/* If animations are reduced at the OS level, use simpler transitions */
@media screen and (prefers-reduced-motion: reduce) {
  .next-enter { opacity: 0; transform: translate3d(100px, 0, 0); }
  .next-enter-active,
  .next-leave-active { transition: 0.5s; }
  .next-leave-to { opacity: 0; transform: translate3d(-100px, 0, 0); }
  
  .prev-enter { opacity: 0; transform: translate3d(-100px, 0, 0); }
  .prev-enter-active,
  .prev-leave-active { transition: 0.5s; }
  .prev-leave-to { opacity: 0; transform: translate3d(100px, 0, 0); }
}

Hier haben wir zwei Übergänge, einen für den Klick des Benutzers auf die "Weiter"-Schaltfläche und einen für die "Zurück"-Schaltfläche. Jeder schiebt die Komponente in die entsprechende Richtung mit der transform-Eigenschaft, aber mit ein paar Extras, um einen Art Quetscheffekt für ein Cartoon-Gefühl zu erzeugen. Wir nutzen auch prefers-reduced-motion, um die Animation zu einer einfacheren Überblendung mit einem kleinen Schiebeeffekt in die entsprechende Richtung zu ändern.

Nun zum JavaScript

methods: {
  changeSlide: function (dir) {
    this.currentSlide = dir === 'next' ? this.currentSlide + 1 : this.currentSlide - 1;
    this.currentTransition = dir;
  }
}

Jede Schaltfläche ruft bei ihrem Klickereignis die Methode changeSlide auf und übergibt die Richtung, die sie repräsentiert. Dann haben wir etwas Logik, um zu verfolgen, welche die aktuelle Folie ist. Eine einzelne Zeile steuert, welcher Übergang verwendet wird. Da die "Weiter"-Schaltfläche "next" als Richtung übergibt, entspricht dies dem "next"-Übergang im CSS. Dasselbe gilt für die "Zurück"-Schaltfläche. Jedes Mal, wenn der Benutzer eine Schaltfläche klickt, weiß die App automatisch, welcher Übergang verwendet werden soll. Somit haben wir schöne Übergangseffekte, die Kontext darüber geben, in welcher Richtung sich der Benutzer durch die Sequenz bewegt.

Beispiel 3: Übergang basierend auf Listenstatus ändern

Für unser letztes Beispiel sehen wir, wie Übergänge basierend auf dem aktuellen Zustand einer Liste innerhalb einer transition-group-Komponente geändert werden können. Die Idee hier ist, dass eine Liste Element für Element mit einem anderen Übergang jedes Mal aktualisiert wird.

Sehen Sie den Pen
VueJS Dynamic Transitions: Change Transition Based on List State
von Travis Almand (@talmand)
auf CodePen.

In diesem Beispiel sehen wir rechts eine Liste von Städten und links eine leere Liste. Während Städte auf der rechten Seite ausgewählt werden, füllen sie die Lücken auf der linken Seite. Die erste Stadt gleitet von oben herein, während sie eingeblendet wird. Die nächsten Städte vor der letzten gleiten entweder von rechts oder links herein, je nach vorherigem Übergang, und die letzte Stadt gleitet von unten herein.

Hier ist das HTML

<transition-group :name="currentListTransition" tag="ul" class="list">
  <li v-for="(item, index) in selectedItems" :key="item">{{ item }}</li>
</transition-group>

Wie üblich eine eher einfache Einrichtung. Hier sind die Übergänge in CSS

.top-enter-active,
.top-leave-active { transition: 0.5s; }
.top-enter,
.top-leave-to {
  opacity: 0;
  transform: translate3d(0, -40px, 0);
}

.top-move {
  opacity: 0.5;
  transition: 0.5s;
}

.left-enter-active,
.left-leave-active { transition: 0.5s; }
.left-enter,
.left-leave-to {
  opacity: 0;
  transform: translate3d(-40px, 0, 0);
}

.left-move {
  opacity: 0.5;
  transition: 0.5s;
}

.right-enter-active,
.right-leave-active { transition: 0.5s; }
.right-enter,
.right-leave-to {
  opacity: 0;
  transform: translate3d(40px, 0, 0);
}

.right-move {
  opacity: 0.5;
  transition: 0.5s;
}

.bottom-enter-active,
.bottom-leave-active { transition: 0.5s; }
.bottom-enter,
.bottom-leave-to {
  opacity: 0;
  transform: translate3d(0, 30px, 0);
}

.bottom-move {
  opacity: 0.5;
  transition: 0.5s;
}

/* If animations are reduced at the OS level, turn off transitions */
@media screen and (prefers-reduced-motion: reduce) {
  .top-enter-active,
  .top-leave-active { transition: none; }
  .top-move { transition: none; }
  .left-enter-active,
  .left-leave-active { transition: none; }
  .left-move { transition: none; }
  .right-enter-active,
  .right-leave-active { transition: none; }
  .right-move { transition: none; }
  .bottom-enter-active,
  .bottom-leave-active { transition: none; }
  .bottom-move { transition: none; }
}

Wie Sie sehen können, ein Übergang für jede mögliche Richtung, in der die Städte in der leeren Liste erscheinen.

Nun zum JavaScript

methods: {
  chooseCity: function (index) {
    let selectedLength = this.selectedItems.length;
    let citiesLength = this.cities.length;
    let clt = this.currentListTransition;
    
    if (selectedLength === 0) {
      clt = 'top';
    } else if (selectedLength > 0 && selectedLength < citiesLength - 1) {
      clt = clt === 'top' || clt === 'left' ? 'right' : 'left';
    } else if (selectedLength === citiesLength - 1) {
      clt = 'bottom';
    }
    
    this.currentListTransition = clt;
    this.selectedItems.push(this.cities[index]);
    document.querySelector(`.city:nth-child(${index + 1})`).classList.add('selected');
  },

  clearSelection: function () {
    this.currentListTransition = 'right';
    this.selectedItems = [];
    document.querySelectorAll('.city.selected').forEach(element => {
      element.classList.remove('selected');
    });
  }
}

Die Methode chooseCity behandelt, was passiert, wenn Sie jede Stadt auswählen. Was uns hauptsächlich interessiert, sind die if- und if/else-Anweisungen in der Mitte der Methode. Wenn Städte ausgewählt werden, schaut die Logik auf die aktuelle Länge des Arrays selectedItems, in das die ausgewählten Städte schließlich eingefügt werden. Wenn die Länge null ist, dann ist dies die erste Stadt, also sollte der Übergang sie von oben kommen lassen. Wenn die Länge zwischen null und der Gesamtzahl unserer Städte-Liste liegt, dann sollte der Übergang von rechts oder links erfolgen. Die neu verwendete Richtung basiert auf der Richtung der vorherigen Übergangsrichtung. Und schließlich, wenn wir bei der letzten auszuwählenden Stadt sind, wird sie zum Bottom-Übergang wechseln. Wieder verwenden wir prefers-reduced-motion, in diesem Fall um die Übergänge ganz auszuschalten.

Eine weitere Option zur Änderung von Übergängen für eine Liste ist die Änderung entsprechend der Art der ausgewählten Elemente; z. B. Ostküsten- versus Westküstenstädte, die jeweils unterschiedliche Übergänge haben. Erwägen Sie die Änderung des Übergangs basierend auf der aktuellen Anzahl der zur Liste hinzugefügten Elemente; zum Beispiel ein anderer Übergang für alle fünf Elemente.

Auf Wiedersehen und danke für all die Übergänge

Nach all diesen Beispielen und Ideen hoffe ich, dass Sie die Transition-Komponente von Vue in Ihren eigenen Projekten nutzen werden. Erkunden Sie die Möglichkeiten, Übergänge und Animationen zu Ihren Apps hinzuzufügen, um Ihren Benutzern Kontext und Interesse zu bieten. In vielen Fällen sind solche Ergänzungen recht einfach zu implementieren, fast schon zu schade, um sie nicht hinzuzufügen. Vue bietet eine aufregende und sehr nützliche Funktion, die Transition-Komponente, "out of the box", und ich kann ihre Verwendung nur ermutigen.

Prost.