Zum Inhalt springen

Slots

Slots ermöglichen es, Template-Inhalte in Komponenten einzufügen.

BaseCard.vue
<template>
<div class="card">
<slot></slot> <!-- Platzhalter für Inhalt -->
</div>
</template>
<!-- Verwendung -->
<template>
<BaseCard>
<h2>Titel</h2>
<p>Beliebiger Inhalt hier...</p>
</BaseCard>
</template>
SubmitButton.vue
<template>
<button type="submit">
<slot>
Submit <!-- Wird gezeigt wenn kein Inhalt übergeben -->
</slot>
</button>
</template>
<!-- Verwendung -->
<template>
<SubmitButton /> <!-- Zeigt "Submit" -->
<SubmitButton>Speichern</SubmitButton> <!-- Zeigt "Speichern" -->
</template>
BaseCard.vue
<template>
<div class="card">
<header>
<slot name="header"></slot>
</header>
<main>
<slot></slot> <!-- Default Slot -->
</main>
<footer>
<slot name="footer"></slot>
</footer>
</div>
</template>
<!-- Verwendung -->
<template>
<BaseCard>
<template #header>
<h2>Kartenheader</h2>
</template>
<p>Hauptinhalt (default slot)</p>
<template #footer>
<button>Aktion</button>
</template>
</BaseCard>
</template>
BaseCard.vue
<template>
<div class="card">
<header v-if="$slots.header">
<slot name="header"></slot>
</header>
<main>
<slot></slot>
</main>
<footer v-if="$slots.footer">
<slot name="footer"></slot>
</footer>
</div>
</template>

Daten von der Kind-Komponente an den Slot-Inhalt übergeben:

ItemList.vue
<script setup>
defineProps(['items'])
</script>
<template>
<ul>
<li v-for="item in items" :key="item.id">
<slot :item="item" :index="index">
{{ item.name }} <!-- Fallback -->
</slot>
</li>
</ul>
</template>
<!-- Verwendung -->
<template>
<ItemList :items="todos">
<template #default="{ item, index }">
<span>{{ index + 1 }}. {{ item.name }}</span>
<button @click="remove(item.id)">X</button>
</template>
</ItemList>
</template>
DataTable.vue
<template>
<table>
<thead>
<tr>
<th v-for="col in columns" :key="col.key">
<slot :name="`header-${col.key}`" :column="col">
{{ col.label }}
</slot>
</th>
</tr>
</thead>
<tbody>
<tr v-for="row in data" :key="row.id">
<td v-for="col in columns" :key="col.key">
<slot :name="`cell-${col.key}`" :row="row" :value="row[col.key]">
{{ row[col.key] }}
</slot>
</td>
</tr>
</tbody>
</table>
</template>
<!-- Verwendung -->
<template>
<DataTable :columns="columns" :data="users">
<template #cell-status="{ value }">
<span :class="value">{{ value }}</span>
</template>
<template #cell-actions="{ row }">
<button @click="edit(row)">Edit</button>
</template>
</DataTable>
</template>

Komponenten, die nur Logik bereitstellen:

MouseTracker.vue
<script setup>
import { ref, onMounted, onUnmounted } from 'vue'
const x = ref(0)
const y = ref(0)
function update(e) {
x.value = e.pageX
y.value = e.pageY
}
onMounted(() => window.addEventListener('mousemove', update))
onUnmounted(() => window.removeEventListener('mousemove', update))
</script>
<template>
<slot :x="x" :y="y"></slot>
</template>
<!-- Verwendung -->
<template>
<MouseTracker v-slot="{ x, y }">
<p>Mouse: {{ x }} / {{ y }}</p>
</MouseTracker>
</template>

Offizielle Vue Dokumentation: