Bikin Komponen Vue.js Makin Fleksibel & Keren Abis Pake Slots: Panduan Lengkap Ngab!

Slots di Vue.js: Panduan Lengkap Menyisipkan Konten Komponen

PPLG

PPLG

Penulis

10 Aug 2026
38 x dilihat

Halo gaes, ngab, sista-sista Vue.js mania! Pernah nggak sih kalian pas lagi asyik-asyiknya ngoding komponen di Vue, terus mikir, "Duh, ini komponen kok kaku banget ya? Maunya sih bisa diisi konten yang beda-beda tiap kali dipake, tapi kok cuma bisa terima props data doang?" Nah, kalau vibes galau itu pernah mampir di pikiran kalian, berarti kalian udah siap banget buat kenalan sama Slots di Vue.js!

Slots ini ibaratnya kayak "lubang" atau "placeholder" di dalam komponen kalian, tempat kalian bisa nyisipin konten apa aja dari komponen parent. Jadi, komponen kalian tetap punya struktur utama, tapi bagian dalamnya bisa custom sesuka hati. Mantul, kan?


Kenapa Slots Penting Banget Buat Dev Vue.js? (Vibesnya Jadi Makin Pro!)

Coba bayangin, kalian punya komponen Card.vue. Nah, satu Card mungkin isinya gambar sama judul, yang lain isinya paragraf panjang, ada juga yang isinya tombol-tombol. Kalau cuma pake props, kalian harus ngirim data image, title, description, buttonText, dll. Jadinya ribet dan kurang fleksibel buat konten yang kompleks.

Nah, di sinilah Slots datang sebagai pahlawan! Dia bikin komponen kalian:

  • Lebih Reusable: Satu komponen bisa dipake buat banyak skenario dengan konten yang beda-beda.
  • Lebih Fleksibel: Konten yang disisipkan bisa berupa markup HTML, komponen lain, atau bahkan logic JavaScript.
  • Lebih Bersih: Logic tentang struktur komponen tetap di child, sementara konten detail diatur di parent.

Jenis-Jenis Slots di Vue.js: Pilih yang Pas Sesuai Kebutuhanmu!

Ada tiga jenis utama Slots yang wajib banget kalian kuasai, gaes. Masing-masing punya vibes dan fungsi sendiri. Skuy, kita bedah satu-satu!

1. Default Slots (Alias: Slot Tanpa Nama)

Ini adalah jenis slot paling basic dan sering kalian jumpai. Ibaratnya kayak satu-satunya pintu masuk ke dalam komponen kalian. Kalau cuma butuh satu "lubang" buat nyisipin konten, Default Slot udah cukup banget.

Gimana Cara Pakenya?

Di Komponen Child (MyButton.vue):

<template>
  <button class="fancy-btn">
    <!-- Di sinilah konten dari parent akan disisipkan -->
    <slot>Klik Aku, Ngab!</slot> 
    <!-- 'Klik Aku, Ngab!' adalah fallback content jika parent tidak menyisipkan apa-apa -->
  </button>
</template>

<style scoped>
.fancy-btn {
  padding: 10px 20px;
  background-color: #42b983;
  color: white;
  border: none;
  border-radius: 5px;
  cursor: pointer;
  font-weight: bold;
}
</style>

Di Komponen Parent (App.vue):

<template>
  <div>
    <MyButton>
      <!-- Konten ini akan masuk ke dalam <slot> di MyButton -->
      <span>Yuk, Pencet!</span>
    </MyButton>

    <MyButton>
      <!-- Ini juga akan masuk, override fallback content -->
      <strong>Submit Sekarang!</strong>
    </MyButton>

    <MyButton></MyButton> 
    <!-- Karena gak ada konten, yang muncul adalah fallback content 'Klik Aku, Ngab!' -->
  </div>
</template>

<script setup>
import MyButton from './components/MyButton.vue';
</script>

2. Named Slots (Alias: Slot Berlabel)

Nah, kalau kalian butuh lebih dari satu "lubang" di komponen kalian (misalnya, satu buat header, satu buat body, satu buat footer), kalian butuh Named Slots. Setiap slot punya "nama" uniknya sendiri.

Gimana Cara Pakenya?

Di Komponen Child (MyCard.vue):

<template>
  <div class="card">
    <header class="card-header">
      <!-- Slot untuk bagian header -->
      <slot name="header">Judul Default Card</slot> 
    </header>
    <div class="card-body">
      <!-- Slot utama untuk isi konten -->
      <slot>Konten Utama Card</slot> 
    </div>
    <footer class="card-footer">
      <!-- Slot untuk bagian footer -->
      <slot name="footer">Footer Default Card</slot> 
    </footer>
  </div>
</template>

<style scoped>
.card {
  border: 1px solid #ddd;
  border-radius: 8px;
  margin: 15px;
  width: 300px;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
}
.card-header {
  padding: 10px 15px;
  background-color: #f8f8f8;
  border-bottom: 1px solid #eee;
  font-weight: bold;
}
.card-body {
  padding: 15px;
}
.card-footer {
  padding: 10px 15px;
  background-color: #f8f8f8;
  border-top: 1px solid #eee;
  text-align: right;
  font-size: 0.9em;
  color: #666;
}
</style>

Di Komponen Parent (App.vue):

Untuk menyisipkan konten ke Named Slots, kalian pakai directive v-slot: diikuti nama slotnya, atau shorthand-nya #. Jangan lupa, konten untuk slot default (tanpa nama) bisa langsung ditulis di antara tag komponen.

<template>
  <div>
    <MyCard>
      <!-- Konten untuk slot 'header' -->
      <template v-slot:header>
        <h1>Profil Developer</h1>
      </template>

      <!-- Konten untuk slot default -->
      <p>Halo gaes, kenalan nih sama developer kece ini!</p>
      <img src="https://via.placeholder.com/150" alt="Profile Picture">
      <p>Suka ngoding dan ngopi.</p>

      <!-- Konten untuk slot 'footer' (pakai shorthand '#') -->
      <template #footer>
        <button>Lihat Selengkapnya</button>
        <small>Dibuat dengan ❤️</small>
      </template>
    </MyCard>

    <MyCard></MyCard> <!-- Tanpa konten, akan muncul semua fallback content -->
  </div>
</template>

<script setup>
import MyCard from './components/MyCard.vue';
</script>

Penting: Kalau kalian pake Named Slots, konten untuk default slot (yang nggak punya name) harus diletakkan langsung di antara tag komponen MyCard, atau bisa juga pakai v-slot:default (tapi ini kurang umum karena bisa langsung).

3. Scoped Slots (Alias: Slot Berdata)

Ini dia nih, the real MVP-nya Slots! Scoped Slots memungkinkan kalian mengirim data dari komponen child kembali ke komponen parent di mana slot itu didefinisikan. Anjay, keren banget kan? Jadi, konten slot di parent bisa berinteraksi sama data yang cuma ada di child. Ini bikin komponen makin powerful dan fleksibel buat UI yang dinamis.

Gimana Cara Pakenya?

Di Komponen Child (MyList.vue):

Kita akan punya list item, dan setiap item punya data unik. Kita mau parent yang memutuskan gimana setiap item itu di-render.

<template>
  <ul class="item-list">
    <li v-for="item in items" :key="item.id">
      <!-- Di sini kita "membocorkan" data item ke parent melalui slot -->
      <slot :item="item" :index="items.indexOf(item)" another-prop="Yo!"></slot>
    </li>
  </ul>
</template>

<script setup>
import { ref } from 'vue';

const items = ref([
  { id: 1, name: 'Buku Vue.js', price: 150000 },
  { id: 2, name: 'Mouse Gaming', price: 300000 },
  { id: 3, name: 'Headset Wireless', price: 750000 }
]);
</script>

<style scoped>
.item-list {
  list-style: none;
  padding: 0;
  width: 300px;
  margin: 15px auto;
  border: 1px solid #eee;
  border-radius: 8px;
}
.item-list li {
  padding: 10px 15px;
  border-bottom: 1px solid #eee;
}
.item-list li:last-child {
  border-bottom: none;
}
</style>

Perhatikan di <slot :item="item" :index="items.indexOf(item)"></slot>. Kita passing item dan index sebagai props ke slot tersebut. Ini yang namanya "slot props".

Di Komponen Parent (App.vue):

Untuk "menangkap" slot props yang dikirim child, kita pakai v-slot lagi, tapi kali ini dengan nilai yang menangkap objek props tersebut (biasanya dinamakan slotProps atau langsung di-destructuring).

<template>
  <div>
    <h2>Daftar Produk</h2>
    <MyList>
      <!-- Kita tangkap slot props-nya di sini -->
      <template v-slot="slotProps">
        <p><strong>{{ slotProps.item.name }}</strong> - Harga: Rp{{ slotProps.item.price.toLocaleString('id-ID') }}</p>
        <small>Item ke-{{ slotProps.index + 1 }}</small>
        <p><i>{{ slotProps.anotherProp }}</i></p>
      </template>
    </MyList>

    <hr>

    <h2>Daftar Produk (Tampilan Lain - Destructuring)</h2>
    <MyList>
      <!-- Bisa juga langsung di-destructuring biar lebih ringkas -->
      <template #default="{ item, index }">
        <div :style="{ backgroundColor: index % 2 === 0 ? '#f0f0f0' : 'white', padding: '8px' }">
          <h3>{{ item.name }}</h3>
          <p>Hanya: Rp{{ item.price.toLocaleString('id-ID') }}</p>
          <p class="tag">#ProdukPilihan</p>
        </div>
      </template>
    </MyList>
  </div>
</template>

<script setup>
import MyList from './components/MyList.vue';
</script>

<style>
.tag {
  color: #42b983;
  font-weight: bold;
}
</style>

Di parent, kita pake <template v-slot="slotProps"> untuk menangkap semua props yang dikirim dari <slot> di child. Kita bisa akses data item dan index dari slotProps.item dan slotProps.index. Atau, biar lebih ringkas dan kece, bisa juga langsung di-destructuring pake <template #default="{ item, index }">. Mantap, kan?


Tips Praktis & Best Practices Biar Ngoding Slots Makin Asik!

  1. Gunakan Default Content: Selalu kasih fallback content di dalam tag <slot> kalian. Ini penting banget biar komponen kalian tetap kelihatan rapi kalau parent lupa (atau memang tidak perlu) nyisipin konten.
  2. Pilih Tipe Slot yang Tepat:
    • Default Slot: Buat komponen yang cuma butuh satu area konten utama (misal: tombol, alert sederhana).
    • Named Slots: Buat komponen dengan layout yang punya beberapa area konten yang berbeda (misal: card dengan header, body, footer).
    • Scoped Slots: Buat komponen yang punya list data dan kalian mau parent yang nentuin gimana setiap item list itu di-render (misal: list produk, tabel data).
  3. Prioritaskan Keterbacaan: Nama slot harus jelas dan deskriptif. Hindari nama yang terlalu umum atau membingungkan.
  4. Hati-hati dengan CSS Scope: Kalau kalian pake scoped style di komponen child, style itu nggak akan ngefek ke konten yang disisipkan via slot (karena konten itu berasal dari parent). Kalau butuh style yang ngaruh ke konten slot, bisa pake global style atau passing class via slot props.
  5. Kombinasi dengan v-if atau v-for: Kalian bisa banget pake directive ini di dalam konten slot kalian di parent, bikin fleksibilitasnya makin gila!

Kesimpulan: Slots Itu Kunci Fleksibilitas Komponen di Vue.js!

Oke gaes, gimana? Udah mulai tercerahkan kan tentang kehebatan Slots di Vue.js? Dari Default Slots yang simpel, Named Slots buat layout multi-area, sampai Scoped Slots yang bikin data dari child bisa ngatur tampilan di parent. Semua ini adalah tool powerful yang bikin komponen kalian jadi super reusable, fleksibel, dan pastinya bikin kode kalian makin bersih.

Jadi, jangan males buat eksplorasi dan latihan terus ya! Coba bikin berbagai komponen pake Slots ini. Dengan begitu, skill Vue.js kalian bakal makin jago dan pede banget buat bikin aplikasi yang scalable dan maintainable. Semangat ngoding, gaes! Kalo ada pertanyaan, jangan sungkan spill di kolom komentar, ngab!


0.0

Berikan Rating

Komentar (0)

Silakan login untuk memberikan komentar.

Login Sekarang

Belum ada komentar. Jadilah yang pertama!

Menyukai Artikel (0)

Belum ada siswa yang menyukai artikel ini.

Pembaca (1)