Props
Daten von Eltern- an Kind-Komponenten weitergeben — typsicher und vorhersagbar.
Was sind Props?
Props (kurz für Properties) sind der Mechanismus, mit dem eine Eltern-Komponente Daten an eine Kind-Komponente übergibt. Sie bilden die öffentliche API einer Komponente — vergleichbar mit Methodenparametern in Ruby.
Rails-Vergleich: Partials mit locals
In Rails übergibst du Daten an Partials über locals: <%= render "card", title: "Hallo", color: "blue" %>. Vue Props funktionieren genauso — nur deklarativ und typsicher.
Props definieren mit defineProps
In der Composition API deklarierst du Props mit dem Compiler-Makro defineProps. Es braucht keinen Import — Nuxt/Vue erkennt es automatisch.
<script setup lang="ts">
// TypeScript-Syntax (empfohlen)
defineProps<{
title: string
subtitle?: string
count: number
}>()
</script>
<template>
<div>
<h2>{{ title }}</h2>
<p v-if="subtitle">{{ subtitle }}</p>
<span>Anzahl: {{ count }}</span>
</div>
</template>TypeScript-Generics bevorzugen
Nutze die generische Syntax defineProps<{ ... }>() statt der Runtime-Variante. So bekommst du volle IDE-Unterstützung und Compile-Time-Checks.
Typvalidierung & Standardwerte
Vue prüft Props zur Laufzeit und warnt in der Konsole, wenn Typen nicht stimmen. Mit withDefaults kannst du Standardwerte setzen.
<script setup lang="ts">
interface Props {
name: string // Pflichtfeld
role?: string // Optional
level?: number // Optional
isActive?: boolean // Optional
}
const props = withDefaults(defineProps<Props>(), {
role: 'Mitglied',
level: 1,
isActive: true,
})
</script>
<template>
<div :class="{ 'opacity-50': !isActive }">
<strong>{{ name }}</strong>
<span class="badge">{{ role }} (Stufe {{ level }})</span>
</div>
</template><template>
<!-- String -->
<UserCard name="Anna" />
<!-- Number (v-bind nötig!) -->
<UserCard :level="5" />
<!-- Boolean (Kurzform = true) -->
<UserCard is-active />
<UserCard :is-active="false" />
<!-- Array -->
<TagList :tags="['Vue', 'TypeScript', 'Nuxt']" />
<!-- Object -->
<ProfileCard :user="{ name: 'Max', age: 28 }" />
<!-- Dynamisch mit v-bind -->
<UserCard v-bind="userProps" />
</template>Einweg-Datenfluss
Props fließen immer von oben nach unten. Eine Kind-Komponente darf Props niemals direkt verändern. Wenn du den Wert lokal anpassen willst, erstelle eine Kopie mit ref() oder computed().
<script setup lang="ts">
const props = defineProps<{
initialCount: number
}>()
// ✅ Lokale Kopie erstellen
const count = ref(props.initialCount)
// ✅ Oder als computed
const doubled = computed(() => props.initialCount * 2)
// ❌ NICHT: props.initialCount = 42
</script>Props nicht mutieren!
Vue gibt eine Warnung aus, wenn du versuchst, einen Prop direkt zu verändern. Erstelle stattdessen immer eine lokale Kopie oder nutze emit, um den Eltern-Wert zu aktualisieren.
Pflichtfelder (required)
In TypeScript-Syntax sind Props ohne ? automatisch Pflichtfelder. Vue warnt, wenn sie beim Verwenden der Komponente fehlen.
<script setup lang="ts">
defineProps<{
// Pflichtfelder (kein ?)
id: number
name: string
// Optionale Felder (mit ?)
description?: string
imageUrl?: string
}>()
</script>
<!-- Verwendung: -->
<!-- ✅ <ProductCard :id="1" name="Widget" /> -->
<!-- ❌ <ProductCard name="Widget" /> → Warnung: id fehlt -->Interaktive Demo
Passe die Props der Karten-Komponente live an — Titel, Farbe und Größe:
Farbe: {{ demoColor }} · Größe: {{ demoSize }}
Zusammenfassung
Kernpunkte
defineProps<T>()definiert die Schnittstelle deiner KomponentewithDefaults()setzt Standardwerte- Props fließen immer einweg — von Parent zu Child
- Pflichtfelder werden durch TypeScript-Syntax erzwungen
- Props nie direkt verändern — lokale Kopie erstellen