Skip to content

Kapitel 16: Komponenten-Kommunikation (Teil 1) - Props

📙 Lernziel: Daten von Eltern- zu Kind-Komponente mit defineProps() übergeben!


16.1 Was sind Props?

Props (Properties) sind Daten, die von einer Eltern-Komponente an eine Kind-Komponente übergeben werden.

Datenfluss: Eltern → Kind (einweg!)

Beispiel-Szenario:

App.vue (Eltern)
  └─ UserCard.vue (Kind)
       Erhält: name, age, city als Props

16.2 Props definieren (defineProps())

In Vue 3 (<script setup>):

vue
<!-- components/UserCard.vue -->
<script setup>
// Props definieren (mit TypeScript)
defineProps<{
  name: string
  age: number
  city?: string  // Optional
}>()

// Oder ohne TypeScript (Runtime-Validierung)
defineProps({
  name: {
    type: String,
    required: true
  },
  age: {
    type: Number,
    default: 0
  },
  city: {
    type: String,
    default: 'Unbekannt'
  }
})
</script>

<template>
  <div class="user-card">
    <h3>{{ name }}</h3>
    <p>Alter: {{ age }}</p>
    <p>Stadt: {{ city }}</p>
  </div>
</template>

<style scoped>
.user-card {
  border: 1px solid #ddd;
  border-radius: 8px;
  padding: 15px;
  margin: 10px;
  max-width: 300px;
}
</style>

16.3 Props übergeben (Eltern-Komponente)

Verwendung in Eltern-Komponente:

vue
<!-- App.vue -->
<script setup>
import UserCard from './components/UserCard.vue'

const users = [
  { name: 'Max', age: 25, city: 'Berlin' },
  { name: 'Anna', age: 30, city: 'München' }
]
</script>

<template>
  <div>
    <h1>Benutzerliste</h1>
    
    <!-- Statische Props -->
    <UserCard name="Karl" :age="40" city="Hamburg" />
    
    <!-- Dynamische Props (mit : ) -->
    <UserCard 
      :name="users[0].name" 
      :age="users[0].age" 
      :city="users[0].city" 
    />
    
    <!-- Mit v-for -->
    <UserCard 
      v-for="user in users" 
      :key="user.name"
      :name="user.name" 
      :age="user.age" 
      :city="user.city" 
    />
  </div>
</template>

16.4 Props Validierung

Runtime-Validierung (ohne TypeScript):

vue
<script setup>
defineProps({
  // Einfache Typ-Prüfung
  title: String,
  
  // Mehrere Typen erlaubt
  likes: [String, Number],
  
  // Pflichtfeld
  isPublished: {
    type: Boolean,
    required: true
  },
  
  // Mit Standardwert
  author: {
    type: Object,
    default: () => ({ name: 'Unbekannt' })
  },
  
  // Benutzerdefinierte Validierung
  age: {
    type: Number,
    validator(value) {
      return value >= 0 && value <= 150
    }
  }
})
</script>

16.5 Props sind read-only!

❌ Props niemals im Kind verändern!

vue
<script setup>
const props = defineProps(['count'])

// ❌ Falsch (Props verändern)
const increment = () => {
  props.count++  // FEHLER! Props sind read-only
}
</script>

✅ Richtige Lösung: Emit verwenden (später) oder lokale Kopie:

vue
<script setup>
import { ref, toRefs } from 'vue'

const props = defineProps(['count'])

// Lokale Kopie erstellen
const localCount = ref(props.count)

// Oder reaktive Referenz (bleibt reaktiv)
const { count } = toRefs(props)
</script>

16.6 Übung: BlogPost-Komponente

Aufgabe: Erstelle eine BlogPost.vue Komponente mit Props.

Lösung:

vue
<!-- components/BlogPost.vue -->
<script setup>
defineProps({
  title: {
    type: String,
    required: true
  },
  content: {
    type: String,
    default: 'Kein Inhalt vorhanden.'
  },
  author: {
    type: String,
    default: 'Anonym'
  },
  publishDate: {
    type: Date,
    default: () => new Date()
  },
  tags: {
    type: Array,
    default: () => []
  }
})
</script>

<template>
  <article class="blog-post">
    <h2>{{ title }}</h2>
    <p class="meta">
      Von {{ author }} am {{ publishDate.toLocaleDateString('de-DE') }}
    </p>
    <p class="content">{{ content }}</p>
    <div class="tags">
      <span v-for="tag in tags" :key="tag" class="tag">{{ tag }}</span>
    </div>
  </article>
</template>

<style scoped>
.blog-post {
  border: 1px solid #ddd;
  border-radius: 8px;
  padding: 20px;
  margin: 20px 0;
}

.meta {
  color: #666;
  font-size: 0.9em;
}

.tags {
  margin-top: 10px;
}

.tag {
  display: inline-block;
  background: #42b883;
  color: white;
  padding: 2px 8px;
  margin: 2px;
  border-radius: 4px;
  font-size: 0.8em;
}
</style>

Verwendung:

vue
<script setup>
import BlogPost from './components/BlogPost.vue'
</script>

<template>
  <div>
    <BlogPost 
      title="Vue 3 lernen" 
      content="Vue 3 ist ein tolles Framework..."
      author="Max"
      :publishDate="new Date('2026-01-15')"
      :tags="['Vue', 'JavaScript', 'Frontend']"
    />
  </div>
</template>

✅ Zusammenfassung

In diesem Kapitel hast du gelernt:

  • ✅ Was Props sind (Eltern → Kind)
  • defineProps() nutzen
  • ✅ Props übergeben (Statisch & Dynamisch)
  • ✅ Props Validierung
  • ✅ Props sind read-only!
  • ✅ Praxis: BlogPost.vue Komponente

🎯 Nächster Schritt: In Kapitel 17 lernst du Events (defineEmits()) - Kind → Eltern!


← Zurück zu Kapitel 15: Komponenten-GrundlagenWeiter zu Kapitel 17: Events & Emits →

Frei für alle Anfänger