Menggunakan Slot di Vue.js: Membangun Komponen Fleksibel dan Reusable

Pendahuluan
Salah satu kekuatan terbesar dalam pengembangan dengan Vue.js adalah kemampuannya untuk membangun komponen yang dapat digunakan kembali. Namun, kadang kita ingin agar komponen tersebut tetap fleksibel — bisa digunakan di berbagai konteks tanpa harus kita ubah struktur internalnya.
Di sinilah fitur slot dalam Vue memainkan peran penting. Slot memungkinkan kita menyisipkan konten dari luar ke dalam komponen, seolah-olah kita memberikan “ruang kosong” yang bisa diisi pengguna komponen sesuai kebutuhan. Fitur ini sangat berguna dalam pembuatan layout, kartu, modal, atau tombol dengan konten yang dinamis.
Dalam artikel ini, kita akan membahas:
- Apa itu slot di Vue.js
- Cara menggunakan default slot
- Penggunaan named slot
- Scoped slot untuk kebutuhan lebih kompleks
- Studi kasus penggunaan slot dalam komponen UI
Apa Itu Slot?
Secara sederhana, slot adalah tempat dalam komponen yang bisa diisi konten dari luar. Ini seperti membuat kerangka, lalu membiarkan pemakai komponen mengisi bagian tertentu.
Contohnya, kamu punya komponen <BaseCard>
yang sudah punya style dan struktur, tapi ingin agar isi kartunya bisa berbeda-beda tergantung pemakaian. Dengan slot, kamu bisa membuka ruang untuk mengisi isi kartu tersebut dari komponen parent.
1. Default Slot: Menyisipkan Konten Dasar
Default slot adalah jenis slot paling sederhana. Konten yang diletakkan di dalam tag komponen akan otomatis ditempatkan di posisi <slot />
di dalam template komponen.
Contoh: BaseCard.vue
<template>
<div class="card">
<slot />
</div>
</template>
<style scoped>
.card {
padding: 1rem;
border: 1px solid #ccc;
border-radius: 8px;
}
</style>
Penggunaan:
<BaseCard>
<h3>Judul Artikel</h3>
<p>Ini konten artikel yang dimasukkan dari luar komponen.</p>
</BaseCard>
Penjelasan:
- Konten
h3
danp
akan disisipkan ke dalam elemen<slot />
diBaseCard.vue
. - Ini memberi fleksibilitas besar tanpa harus menduplikasi struktur komponen.
2. Named Slot: Memberi Nama Slot untuk Kontrol Lebih Baik
Kadang, kita butuh lebih dari satu slot dalam komponen. Misalnya, kita ingin membedakan antara bagian header, body, dan footer. Untuk itu, kita bisa menggunakan named slot.
Contoh: ModalDialog.vue
<template>
<div class="modal">
<header class="modal-header">
<slot name="header" />
</header>
<section class="modal-body">
<slot name="body" />
</section>
<footer class="modal-footer">
<slot name="footer" />
</footer>
</div>
</template>
Penggunaan:
<ModalDialog>
<template #header>
<h2>Konfirmasi</h2>
</template>
<template #body>
<p>Apakah kamu yakin ingin menghapus item ini?</p>
</template>
<template #footer>
<button>Batal</button>
<button>Hapus</button>
</template>
</ModalDialog>
Penjelasan:
- Setiap slot diberi nama (
header
,body
,footer
) agar bisa disisipkan dengan lebih terstruktur. #header
adalah shorthand dariv-slot:header
.
3. Scoped Slot: Mengakses Data dari Komponen Anak
Scoped slot digunakan ketika kita ingin menerima data dari komponen anak untuk digunakan dalam konten slot. Ini berguna untuk membuat komponen yang bisa memberikan data ke pemakainya.
Contoh: ListRenderer.vue
<template>
<ul>
<li v-for="item in items" :key="item.id">
<slot :item="item" />
</li>
</ul>
</template>
<script setup>
const props = defineProps({
items: Array
});
</script>
Penggunaan:
<ListRenderer :items="produk">
<template #default="{ item }">
<strong>{{ item.nama }}</strong> - Rp{{ item.harga }}
</template>
</ListRenderer>
<script setup>
const produk = [
{ id: 1, nama: 'Kopi', harga: 18000 },
{ id: 2, nama: 'Teh', harga: 15000 }
];
</script>
Penjelasan:
- Komponen
ListRenderer
memberikan dataitem
dari dalamnya ke slot. - Pemakai komponen bebas menampilkan setiap item sesuai kebutuhan — ini sangat fleksibel!
Studi Kasus: Membuat Komponen Layout Reusable
Bayangkan kita ingin membuat layout PageWrapper
yang bisa digunakan di banyak halaman, tetapi isi halaman bisa berbeda. Kita bisa kombinasikan default dan named slot.
PageWrapper.vue
<template>
<div class="page">
<header><slot name="title" /></header>
<main><slot /></main>
<footer><slot name="footer" /></footer>
</div>
</template>
<style scoped>
.page {
max-width: 800px;
margin: 0 auto;
}
</style>
Penggunaan:
<PageWrapper>
<template #title>
<h1>Profil Pengguna</h1>
</template>
<p>Ini adalah konten utama halaman profil pengguna.</p>
<template #footer>
<small>© 2025 MyApp</small>
</template>
</PageWrapper>
Slot di Vue.js memungkinkan kita untuk membangun komponen yang lebih fleksibel, reusable, dan dinamis. Dengan memahami:
- Default slot untuk konten dasar
- Named slot untuk struktur konten kompleks
- Scoped slot untuk mentransfer data dari anak ke parent