Bedingte Darstellung
Elemente dynamisch ein- und ausblenden mit v-if, v-else und v-show
Einführung
In fast jeder Anwendung musst du Inhalte bedingt anzeigen: Fehlermeldungen, Ladezustände, verschiedene Ansichten je nach Benutzerrolle. Vue bietet dafür zwei Ansätze: v-if (Element wird aus dem DOM entfernt) und v-show (Element wird per CSS versteckt).
Rails-Vergleich: ERB Conditionals
In Rails-Views verwendest du Ruby-Conditionals innerhalb von ERB-Tags. Das Ergebnis wird einmalig auf dem Server berechnet. In Vue sind Bedingungen reaktiv — änderst du den Wert, aktualisiert sich die Anzeige sofort.
<!-- Rails: Server-seitig, einmalig -->
<% if @user.admin? %>
<div class='admin-panel'>Admin-Bereich</div>
<% elsif @user.moderator? %>
<div class='mod-panel'>Moderator-Bereich</div>
<% else %>
<div class='user-panel'>Benutzer-Bereich</div>
<% end %>
<!-- Oft auch mit Hilfsmethoden -->
<%= render 'admin_panel' if @user.admin? %><!-- Vue: Client-seitig, reaktiv -->
<div v-if="user.role === 'admin'" class='admin-panel'>
Admin-Bereich
</div>
<div v-else-if="user.role === 'moderator'" class='mod-panel'>
Moderator-Bereich
</div>
<div v-else class='user-panel'>
Benutzer-Bereich
</div>v-if — Bedingt rendern
v-if rendert ein Element nur, wenn die Bedingung truthy ist. Ist die Bedingung falsy, wird das Element komplett aus dem DOM entfernt.
<script setup>
import { ref } from 'vue'
const istAngemeldet = ref(false)
const hatNachrichten = ref(true)
const nachrichtenAnzahl = ref(5)
</script>
<template>
<!-- Einfaches v-if -->
<p v-if="istAngemeldet">Willkommen zurück!</p>
<!-- v-if mit Vergleich -->
<span v-if="nachrichtenAnzahl > 0" class="badge">
{{ nachrichtenAnzahl }} neue Nachrichten
</span>
<!-- v-if mit logischen Operatoren -->
<div v-if="istAngemeldet && hatNachrichten">
Du hast ungelesene Nachrichten!
</div>
</template>v-else-if und v-else
Wie in jeder Programmiersprache kannst du v-else-if und v-else für Verzweigungen verwenden. Wichtig: Sie müssen direkt nach einem v-if bzw. v-else-if-Element stehen — ohne Elemente dazwischen.
<script setup>
import { ref } from 'vue'
const status = ref('laden') // 'laden' | 'erfolg' | 'fehler' | 'leer'
const punktzahl = ref(75)
</script>
<template>
<!-- Ladezustand-Muster (sehr häufig!) -->
<div v-if="status === 'laden'">
⏳ Daten werden geladen...
</div>
<div v-else-if="status === 'fehler'">
❌ Ein Fehler ist aufgetreten.
</div>
<div v-else-if="status === 'leer'">
📭 Keine Daten vorhanden.
</div>
<div v-else>
✅ Daten erfolgreich geladen!
</div>
<!-- Bewertung -->
<p v-if="punktzahl >= 90">🏆 Sehr gut!</p>
<p v-else-if="punktzahl >= 70">👍 Gut</p>
<p v-else-if="punktzahl >= 50">📝 Ausreichend</p>
<p v-else>❌ Nicht bestanden</p>
</template>Häufiger Fehler: Element dazwischen
v-else und v-else-if müssen direkt auf ein v-if-Element folgen. Ein Element dazwischen bricht die Kette:
<!-- ❌ FALSCH: <p> unterbricht die Kette -->
<div v-if="a">A</div>
<p>Irgendein Text</p>
<div v-else>B</div> <!-- Vue-Fehler! -->
<!-- ✅ RICHTIG: Direkt aufeinander -->
<div v-if="a">A</div>
<div v-else>B</div>template v-if — Gruppen bedingt rendern
Was, wenn du mehrere Elemente gleichzeitig bedingt anzeigen willst, aber kein Wrapper-Element im DOM haben möchtest? Verwende <template> als unsichtbaren Container:
<template>
<!-- template wird NICHT im DOM gerendert -->
<template v-if="istAngemeldet">
<h2>Dashboard</h2>
<nav>Navigation für angemeldete Benutzer</nav>
<main>Dein persönlicher Bereich</main>
</template>
<template v-else>
<h2>Willkommen</h2>
<p>Bitte melde dich an, um fortzufahren.</p>
<button>Anmelden</button>
</template>
</template>Warum template statt div?
Ein <div> als Wrapper würde ein zusätzliches Element im DOM erzeugen, das Layout und CSS beeinflussen kann. <template> ist ein „unsichtbarer" Container — Vue rendert nur den Inhalt, nicht das Template-Tag selbst.
v-show — Per CSS ein-/ausblenden
v-show schaltet nur die CSS-Eigenschaft display um. Das Element bleibt immer im DOM — es wird nur visuell versteckt.
<script setup>
import { ref } from 'vue'
const istSichtbar = ref(true)
</script>
<template>
<button @click="istSichtbar = !istSichtbar">Toggle</button>
<!-- v-show: Immer im DOM, nur display: none -->
<div v-show="istSichtbar">
Ich bin sichtbar!
</div>
<!-- Im DOM wenn istSichtbar === false: -->
<!-- <div style="display: none;">Ich bin sichtbar!</div> -->
</template>v-if vs v-show — Wann was verwenden?
<!-- v-if: Element wird komplett entfernt/eingefügt -->
<!-- ✅ Gut für: Selten wechselnde Bedingungen -->
<!-- ✅ Gut für: Große Bereiche mit vielen Kind-Elementen -->
<!-- ✅ Unterstützt: v-else-if, v-else -->
<!-- ❌ Teurer bei häufigem Wechsel -->
<div v-if="istAdmin">Admin-Panel</div>
<!-- v-show: Element bleibt im DOM, nur CSS toggle -->
<!-- ✅ Gut für: Häufiges Umschalten (Tabs, Tooltips) -->
<!-- ✅ Schneller Toggle-Wechsel -->
<!-- ❌ Element ist IMMER im DOM (auch wenn versteckt) -->
<!-- ❌ Kein v-else, kein template v-show -->
<div v-show="istSichtbar">Tooltip-Inhalt</div>Faustregel
v-if = Höhere Kosten beim Umschalten, niedrigere Kosten wenn nicht gerendert. Wähle v-if, wenn sich die Bedingung selten ändert.
v-show = Niedrige Kosten beim Umschalten, Element ist immer im DOM. Wähle v-show, wenn du häufig umschaltest (z.B. Tabs, Dropdown-Menüs).
Einschränkungen von v-show
<!-- ❌ v-show funktioniert NICHT auf <template> -->
<template v-show="ok"> <!-- Fehler! -->
<p>Das geht nicht</p>
</template>
<!-- ❌ v-show hat KEIN v-else -->
<div v-show="ok">Ja</div>
<div v-show="!ok">Nein</div> <!-- So musst du es machen -->
<!-- ✅ v-if unterstützt beides -->
<template v-if="ok">
<p>Ja</p>
</template>
<template v-else>
<p>Nein</p>
</template>Interaktive Demo
Probiere v-if und v-show selbst aus und beobachte die Unterschiede:
v-if / v-else-if / v-else — Statusanzeige
⏳ Lädt... Daten werden vom Server geholt.
v-if vs v-show — Vergleich
v-if="true"
v-show="true"
Bewertungs-Rechner mit v-if
Benutzerdetails ein-/ausblenden
Zusammenfassung
Das Wichtigste auf einen Blick
v-if— Element wird komplett aus dem DOM entfernt/eingefügtv-else-if/v-else— Verzweigungen (müssen direkt aufeinander folgen)v-show— Nur CSSdisplay: noneToggle<template v-if>— Gruppen bedingt rendern ohne Wrapper- Faustregel:
v-iffür seltene Wechsel,v-showfür häufige v-showhat keinv-elseund funktioniert nicht auf<template>