Start / Cheat Sheets

Cheat Sheet

Vue 3 Kern — Cheat Sheet

Stand: · Vue.js Grundlagen & Composition API

Vue.jsVue 3Composition APIv-model

Der Spickzettel zur Komponente selbst: Aufbau, Template, Reaktivität, Formulare, Aussehen. Für alles, was aus Komponenten eine Anwendung macht — Props und Slots, Router, HTTP, Pinia, Deployment — gibt es ein zweites Blatt: Vue 3 Anwendung.

Maßgeblich ist und bleibt die offizielle Vue-Dokumentation; dieses Blatt ist eine Auswahl für den Alltag, keine Referenz.

Projekt anlegen und lesen

npm create vue@latest    # ohne @latest zieht npm ggf. eine alte Fassung
cd leihkiste && npm install && npm run dev

Vue 3.5 verlangt Node ^22.18.0 oder >=24.12.0 — eine ältere Version bricht erst beim Scaffolding ab, nicht bei der Installation. create-vue ist reines Scaffolding, den Rest übernimmt Vite; die alte Vue CLI (vue create, webpack) ist im Wartungsmodus.

PfadInhalt
src/main.jsEinstiegspunkt, erzeugt und hängt die Anwendung ein
src/App.vueWurzelkomponente
src/components/Wiederverwendbare Komponenten
src/views/Komponenten, die eine Route füllen
src/router/, src/stores/Routenkonfiguration, Pinia-Stores
src/assets/läuft durch den Build, bekommt einen Hash im Namen
public/wird unverändert kopiert, feste URL

views ist eine Konvention des Gerüsts, kein Vue-Begriff. Alles zwischen createApp und app.mount() gilt app-weit — was nach mount kommt, greift nicht mehr.

Modul: Einführung und Projektsetup

Single-File Component und Registrierung

BlockEnthältPflicht
script setupZustand und Funktionennein
templateStruktur der Ausgabepraktisch ja
styleAussehen, gern scopednein
<script setup>
import { ref } from 'vue'
import ArtikelKarte from './components/ArtikelKarte.vue'  // Import genügt
const anzahl = ref(0)
</script>
<template>
  <ArtikelKarte />
  <button @click="anzahl++">Anzahl: {{ anzahl }}</button>
</template>

Ohne script setup ist keine Variable im Template sichtbar, auch keine importierte. Die ausgeschriebene Form macht sichtbar, warum: nur was setup() zurückgibt, landet im Template.

LokalGlobal (app.component)
Sichtbarkeitnur in dieser Dateiüberall
Tree Shakinggreiftgreift nicht
Herkunft im Codesteht im Importmuss gesucht werden
Vererbung an Kinderneinentfällt

Lokale Registrierung vererbt sich nicht — Kindkomponenten brauchen ihren eigenen Import. Global bleibt die Ausnahme für die wenigen Bausteine, die wirklich überall vorkommen.

KonventionBegründung
Dateinamen in PascalCaseDatei und Tagname stimmen überein
Mehrwortige Komponentennamenkeine Kollision mit HTML-Elementen
Basis-Präfix für BausteineBasisKnopf ist erkennbar generisch
views/ für Routenzieletrennt Seite vom Baustein
Ein Ordner je FachbereichZusammengehöriges liegt beieinander

Konventionen wirken nur, wenn sie ausnahmslos gelten — sonst sind sie Rauschen.

Modul: Komponentenbasierte Entwicklung

Template-Syntax

In einer Bindung steht genau ein Ausdruck — kein Statement, keine Ablaufsteuerung.

ErlaubtNicht erlaubt
anzahl + 1var a = 1
ok ? 'Ja' : 'Nein'if (ok) { ... }
name.toUpperCase()mehrere Anweisungen
formatiere(datum)Zugriff auf eigene window-Werte
LangformKurzformFür
v-bind:src:srcAttribute
v-on:click@clickEreignisse
v-slot:kopf#kopfSlots
v-bind:[a]:[a]dynamisches Argument
:idGleichnamen-Kurzform für :id="id", ab 3.4

v-if und v-for haben keine Kurzform. v-bind="objekt" setzt mehrere Attribute auf einmal; bei Kollision gewinnt die spätere Angabe. v-html rendert rohes HTML — mit Nutzerinhalt ist das eine XSS-Lücke.

Modul: Templates und Datenbindung

Ereignis-Modifikatoren

ModifikatorWirkung
.preventpreventDefault auf dem Ereignis
.stopstopPropagation, kein Weiterreichen
.onceHandler feuert genau einmal
.selfnur wenn das Ziel das Element selbst ist
.enternur bei der Taste Enter

Verkettbar (@click.stop.prevent), und die Reihenfolge zählt: .prevent.self ist nicht .self.prevent. Ereignisnamen sind kleingeschrieben — @keyUp funktioniert nicht.

Modul: Templates und Datenbindung

Bedingung und Liste

v-ifv-show
Im DOM bei falschneinja
Erstes Rendernfaul, nur bei wahrimmer
Umschaltkostenhöherniedrig
Auf templatejanein
Mit v-elsejanein

Häufiges Umschalten spricht für v-show, seltenes Ändern für v-if. Unter v-if läuft der Lebenszyklus der Kinder wirklich ab — innerer Zustand geht beim Umschalten verloren, und das ist Absicht.

<!-- v-if und v-for nie auf demselben Element: v-if gewinnt und kennt a nicht -->
<template v-for="a in artikel" :key="a.id">
  <li v-if="a.verfuegbar">{{ a.name }}</li>
</template>

Ohne key ordnet Vue nach Position und verwechselt Elemente beim Umsortieren; der Index als key ist ebenfalls nur die Position. Ein key muss primitiv sein.

Modul: Templates und Datenbindung

Reaktivität: ref, reactive, computed

WerkzeugFürBesonderheit
refjeden Wert.value im Skript
reactiveObjektenicht ersetzbar
computedAbleitungenmerkt sich Ergebnisse
shallowRefgroße Objektenur .value verfolgt
readonlyWeitergabeschützt vor Änderung

Als Regel: ref für alles, computed für Ableitungen, der Rest bei konkretem Bedarf.

Stelleref
im Skript.value nötig
im Template, oberste Ebenewird ausgepackt
als Feld eines reactivewird ausgepackt
in einem Array.value nötig
in Map oder Set.value nötig

Die letzten beiden Zeilen sind der häufigste Stolperstein überhaupt.

computedMethode
Ergebnis gemerktjanein
Neuberechnungbei Abhängigkeitbei jedem Rendern
Aufruf im Templateohne Klammernmit Klammern
Argumenteneinja
// Getter bleibt frei von Nebenwirkungen; sort/reverse vorher kopieren
const verfuegbareAnzahl = computed(() => artikel.value.filter(a => a.verfuegbar).length)

// Schreibbares computed — die Ausnahme, nicht der Normalfall
const vollerName = computed({
  get() { return vorname.value + ' ' + nachname.value },
  set(neu) { [vorname.value, nachname.value] = neu.split(' ') }
})

Modul: Composition API und Reaktivität · Templates und Datenbindung

Makros in script setup

MakroZweck
definePropsEingaben deklarieren
defineEmitsEreignisse deklarieren
defineModelv-model entgegennehmen, ab 3.4
defineExposenach außen sichtbar machen
defineOptionsKomponentenoptionen setzen, ab 3.3
defineSlotsSlot-Typen angeben, ab 3.3

Makros werden nicht importiert, der Compiler kennt sie — und sie lassen sich nicht in Bedingungen oder Funktionen aufrufen. Eine Komponente in script setup ist von außen geschlossen, bis defineExpose sie öffnet.

Modul: Composition API und Reaktivität

Lifecycle-Hooks und Composables

HookZeitpunkt
onBeforeMountvor dem ersten Einhängen
onMountednach dem Einhängen, DOM steht
onBeforeUpdate / onUpdatedvor / nach der Aktualisierung
onBeforeUnmountvor dem Abbau
onUnmountednach dem Abbau, Effekte gestoppt
onErrorCapturedbei Fehler aus einem Nachfahren

Dazu onActivated / onDeactivated für KeepAlive. Registrierung muss synchron im Setup erfolgen — in einem then oder nach einem await registriert der Hook nichts.

// composables/useFilter.js — refs zurückgeben, damit das Zerlegen reaktiv bleibt
export function useFilter(artikel) {
  const suche = ref('')
  const treffer = computed(() => artikel.value.filter(a => passt(a, suche.value)))
  return { suche, treffer }
}

Ein reactive-Objekt als Rückgabe verhindert genau das. Zustand außerhalb der Funktion zu deklarieren teilt ihn ungewollt über alle Aufrufer.

Modul: Composition API und Reaktivität

Formulare und v-model

v-model ist kein Zwei-Wege-Kanal, sondern Bindung plus Listener:

<input :value="text" @input="e => text = e.target.value">
<input v-model="text">   <!-- gleichwertig -->
ElementEigenschaftEreignis
input Text und textareavalueinput
input checkbox und radiocheckedchange
selectvaluechange
ModifikatorWirkungTypischer Fall
.lazyerst bei change statt inputlange Texte
.numberwandelt in eine ZahlMengenangabe
.trimschneidet Leerraum abNamen und Codes

Bei type="number" wirkt .number automatisch. .trim greift beim Setzen, nicht rückwirkend.

FeldStartwertErgebnis
eine Checkboxfalsetrue oder false
mehrere Checkboxenleeres ArrayArray der Werte
Radiogruppeleerer StringWert der Option
select einfachleerer StringWert der Option
select mit multipleleeres ArrayArray der Werte

Ein Startwert vom falschen Typ bricht die Bindung stumm. Eigene Wahrheitswerte setzt man über true-value / false-value.

<!-- v-model in der eigenen Komponente, ab Vue 3.4 -->
<script setup>
const menge = defineModel({ default: 1 })   // → Prop modelValue + update:modelValue
</script>

defineModel('titel') erzeugt Prop titel und Ereignis update:titel; mehrere v-model an einer Komponente sind damit möglich. Veränderliche Vorgabewerte gehören in eine Funktion, sonst teilen sich Instanzen ein Objekt.

Prüfungen gehören als computed neben den Zustand, nicht in einen Watcher — dort entstehen leicht Schleifen. Neben den Werten braucht ein Formular eigene Zustände: sendet (Sperre, sonst legt ein Doppelklick zwei Datensätze an), abgesendet, beruehrt, serverFehler.

Modul: Formularverarbeitung

Styling: scoped, Klassen, Preprozessoren

scoped hängt jedem Selektor ein data-v-…-Attribut an — Kapselung ist das nicht, globale Selektoren wirken weiter hinein.

SelektorWirkt aufTypischer Fall
:deep(…)Inneres einer Kindkomponentefremde Komponente anpassen
:slotted(…)hereingereichten InhaltLayout des Slots
:global(…)die ganze SeiteKlasse am body

Alle drei gelten nur innerhalb eines scoped-Blocks; die alten Pfeil-Formen sind veraltet.

FallSyntax
Klasse an- und ausschaltenObjekt: :class="{ frei: offen }"
Klassenname aus einer VariableArray: :class="[basis, zustand]"
Mehrere Zustände zugleichObjekt im computed

Statisches class und gebundenes :class ergänzen sich, sie ersetzen sich nicht. Auf einer Komponente landet die Klasse am Wurzelelement — bei mehreren Wurzeln braucht es $attrs.class.

<style scoped>
p { color: v-bind(farbe); }   /* wird zu einer CSS-Variablen, bleibt aktuell */
</style>
SprachePaketlang-Attribut
Sass und SCSSsass-embedded oder sassscss oder sass
Lesslessless
Stylusstylusstylus

Kein Vite-Plugin und kein Eintrag in vite.config.js nötig, die Erkennung läuft über lang. Sass-Variablen sind Bauzeit-Werte und lassen sich zur Laufzeit nicht ändern — für Themes und dunklen Modus gewinnen deshalb CSS-Variablen.

Modul: Styling von Komponenten

Typische Fallen

  • Vergessenes .value liefert das ref-Objekt statt des Werts — meist als NaN sichtbar.
  • reactive neu zuweisen kappt die Reaktivität still; Zerlegen liefert gewöhnliche Werte ohne Verbindung.
  • computed, das Date.now() liest, aktualisiert nie — das ist keine reaktive Quelle.
  • onMounted nach einem await registriert nichts. Zu jedem addEventListener gehört das Gegenstück im onUnmounted.
  • Props direkt ändern ist verboten. Ein geändertes Prop-Objekt wirkt trotzdem nach oben — Objekte sind Referenzen.
  • Ohne .prevent lädt das Formular die Seite neu und der Zustand ist weg.
  • v-show auf <template> wirkt nicht, es gibt kein Element zum Schalten.
  • Ohne Doppelpunkt ist der Attributwert eine Zeichenkette, kein Ausdruck.
  • .vue gehört in den Importpfad, sie ist nicht optional; Komponententags in PascalCase, sonst kollidieren sie mit HTML-Elementen.
  • Vue-2-Filter mit dem senkrechten Strich lösen heute einen Fehler aus; Vue 2 ist seit Ende 2023 ohne Support.
  • :deep ohne scoped ist wirkungslos — und koppelt zwei Dateien fest aneinander, wo es wirkt.

Module: alle sechs des Kern-Teils

Zum Seminar Vue.js Grundlagen & Composition API