Slots: Menyisipkan Konten ke Komponen
Slot default dan fallback, slot bernama, scoped slot untuk membagikan data ke induk, v-slot dan singkatan #, serta pola komponen layout.
Props untuk data, slot untuk tampilan
Props cocok untuk mengirim angka atau teks. Tetapi bagaimana jika kita ingin memberi komponen potongan template — misalnya isi kartu berupa gambar + tombol, atau isi modal berupa form? Untuk itu ada slot: "lubang" dalam komponen tempat induk menyuntikkan konten sendiri.
Slot default
<!-- Kartu.vue -->
<template>
<div class="kartu">
<slot />
</div>
</template>
<!-- pemakaian -->
<Kartu>
<h3>Halo</h3>
<p>Ini isi kartu.</p>
</Kartu>
Apa pun yang ditulis di antara tag pembuka-penutup komponen akan menggantikan <slot />.
Fallback content
Isi di dalam <slot> dipakai jika induk tidak mengirim apa-apa:
<slot>Tidak ada konten</slot>
Slot bernama
Untuk beberapa lubang, beri nama. Induk mengisinya dengan <template #nama> (singkatan dari v-slot:nama).
<!-- Kartu.vue -->
<div class="kartu">
<header><slot name="header" /></header>
<main><slot /></main> <!-- slot default -->
<footer><slot name="footer">Tanpa footer</slot></footer>
</div>
<!-- pemakaian -->
<Kartu>
<template #header><h3>Judul</h3></template>
<p>Isi utama (masuk slot default)</p>
<template #footer><small>© 2026</small></template>
</Kartu>
Scoped slot: anak membagikan data ke slot
Kadang tampilan ditentukan induk, tetapi datanya dimiliki anak (misal tiap baris daftar). Anak "mengoper" data lewat atribut pada <slot>; induk menerimanya dengan v-slot.
<!-- Daftar.vue -->
<script setup>
defineProps({ items: Array })
</script>
<template>
<ul>
<li v-for="item in items" :key="item">
<slot :item="item" :nomor="items.indexOf(item) + 1">{{ item }}</slot>
</li>
</ul>
</template>
<!-- pemakaian: slot default menerima props slot -->
<Daftar :items="['Apel', 'Jeruk']" v-slot="{ item, nomor }">
{{ nomor }}. ⭐ {{ item }}
</Daftar>
Untuk slot bernama: <template #baris="{ item }">.
| Jenis | Kapan dipakai |
|---|---|
| Default slot | Satu area konten bebas |
| Named slot | Beberapa area (header/body/footer) |
| Scoped slot | Induk perlu data dari anak untuk menentukan tampilan |
Mengecek slot terisi
<footer v-if="$slots.footer"><slot name="footer" /></footer>
Aturan scope
Konten slot ditulis di induk, sehingga hanya bisa mengakses data induk — bukan data internal anak (kecuali yang dikirim lewat scoped slot).
Kesalahan umum
- Mencampur konten bebas dengan
<template #default>eksplisit sehingga ambigu. - Mengakses variabel milik anak langsung di konten slot — tidak bisa; pakai scoped slot.
- Lupa memberi nama unik pada slot sehingga dua
<slot />default saling menimpa.