Seperti yang telah saya jelaskan di Dasar Pembuatan Komponen Vue.js, slot digunakan agar pengisian konten pada template komponen Vue dapat dilakukan secara dinamis (tidak perlu hard-coded lagi). Kali ini, saya akan membandingkan perbedaan penggunaan slot (biasa), named slots dan scoped slots. Dengan mengetahui variasi penggunaan ketiganya, penyisipan konten ke dalam template dapat dilakukan lebih fleksibel.

Penggunaan Slot (Biasa)

Buat file baru latihan014.html kemudian copy paste kode berikut :

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>Latihan Vue 014</title>
    <link rel="stylesheet" href="bootstrap.min.css">
</head>
<body>
    <div id="app">
        <div class="jumbotron text-center">
            <h1>Bootstrap 4</h1>
            <p>Latihan014 - Penggunaan Slot, Named Slots dan Scoped Slots pada Vue.js</p>
          </div>
        <div class="container">
            
            <div class="row">

                <div class="col-md-6">
                    <contoh-slot-biasa nama="Varian Hermianto" whatsapp="08-222-666-777-8">
                    </contoh-slot-biasa>
                </div>

                <div class="col-md-6">
                    <contoh-slot-biasa nama="Varian Hermianto" whatsapp="08-222-666-777-8">
                        Juventini yang kada-kadang Hala Madrid.
                    </contoh-slot-biasa>
                </div>

            </div>

        </div>
    </div>
    <script src="vue.js"></script>
    <script src="latihan014.js"></script>
</body>
</html>

dan juga file latihan014.js dengan baris kode :

Vue.component('ContohSlotBiasa', {
    props: ['nama', 'whatsapp'],
    template: `
        <div style="margin-top: 20px;">
            <div class="card">
                <div class="card-body">

                    <p class="card-text">Contoh Slot Biasa</p>
                    
                    <hr/>
                    
                    <h4 class="card-title">{{ nama }}</h4>
                    
                    <p class="card-text">
                        <slot>Deskripsi Default</slot>
                    </p>
                    
                    <hr/>
                    
                    <p class="card-text"><strong>Kontak WA :</strong> {{ whatsapp }}</p>
                    
                </div>
            </div>
        </div>
    `
});

new Vue ({    
    el: '#app'
});

Slot <slot>Deskripsi Default</slot> di dalam template akan bernilai “Deskripsi Default” apabila pemanggilan komponen ContohSlotBiasa tidak disertai deskripsi :

<div class="col-md-6">
    <contoh-slot-biasa nama="Varian Hermianto" whatsapp="08-222-666-777-8">
    </contoh-slot-biasa>
</div>

Berikut adalah hasil eksekusi file latihan014.html yang menunjukkan perbandingan antara slot tanpa deskripsi (card sebelah kiri) dengan slot disertai deskripsi (card sebelah kanan) :

penggunaan slot, named slots dan scoped slots pada vue.js

Penggunaan Named Slots

Tambahkan baris kode berikut ke dalam elemen <div class="container"></div> pada file latihan014.html :

<div class="row">

    <div class="col-md-6">
        <contoh-named-slots>
            <template slot="nama"></template>
            <p class="card-text" slot="whatsapp"></p>
        </contoh-named-slots>
    </div>

    <div class="col-md-6">
        <contoh-named-slots>
            <template slot="nama">
                <u><i>Varian Hermianto</i></u>
            </template>
            Juventini yang kada-kadang <u><i>Hala Madrid</i></u>.
            <p class="card-text" slot="whatsapp">
                <strong>Kontak WA :</strong> 08-222-666-777-8
            </p>
        </contoh-named-slots>
    </div>

</div>

lalu tambahkan komponen berikutnya sesuai nama tag <contoh-named-slots> baris kode di atas ke file latihan014.js :

Vue.component('ContohNamedSlots', {
    template: `
        <div style="margin-top: 20px;">
            <div class="card">
                <div class="card-body">
                
                    <p class="card-text">Contoh Named Slots</p>

                    <hr/>

                    <h4 class="card-title">
                        <slot name="nama">Nama Default</slot>
                    </h4>

                    <p class="card-text">
                        <slot>Deskripsi Default</slot>
                    </p>

                    <hr/>

                    <slot name="whatsapp">WA Default</slot>

                </div>
            </div>
        </div>
    `
});

Pada template komponen ContohNamedSlots, slot <slot name="nama"> ditulis di dalam elemen <h4 class="card-title"></h4>. Oleh karena itu, pengisian konten dari halaman HTML wajib menyertakan kata kunci template :

<template slot="nama">
    Varian Hermianto
</template>

Sebaliknya, penulisan slot <slot name="whatsapp"> tidak berada di dalam elemen atau diapit oleh tag HTML, maka pengisian konten dari halaman HTML dapat dikaitkan dengan tag (misal <p>) :

<p class="card-text" slot="whatsapp">
    <strong>Kontak WA :</strong> 08-222-666-777-8
</p>

Di pemanggilan komponen ContohNamedSlots pertama (card sebelah kiri), semua slot sengaja saya kosongkan, agar terlihat jelas perbedaannya dengan yang terisi slot-nya :

<div class="col-md-6">
    <contoh-named-slots>
        <template slot="nama"></template>
        <p class="card-text" slot="whatsapp"></p>
    </contoh-named-slots>
</div>

Slot nama yang kosong akan diisi “Nama Default”, begitu pula dengan slot deskripsi yang kosong digantikan oleh “Deskripsi Default”. Pengecualian untuk slot whatsapp yang kontennya diisi melalui tag HTML <p>, nilai “WA Default” tidak tertampil.

penggunaan slot, named slots dan scoped slots pada vue.js

Penggunaan Scoped Slots

Berbeda dari slot (biasa) dan named slots yang digunakan untuk mengisi konten dari halaman HTML ke template komponen Vue, pada Scoped Slots, konten telah tersedia di template dan siap dibaca / ditampilkan pada halaman HTML.

Slot cukup ditulis sekali di template komponen ContohScopedSlots, tapi dapat memiliki beberapa props sekaligus namaProgrammer, waProgrammer, deskripsiProgrammer :

Vue.component('ContohScopedSlots', {
    props: ['nama'],
    template: `
        <div style="margin-top: 20px;">
            <div class="card">
                <div class="card-body">
                
                    <slot 
                        :namaProgrammer=nama 
                        waProgrammer="08-222-666-777-8"
                        :deskripsiProgrammer=deskripsi
                    >Konten Default</slot>

                </div>
            </div>
        </div>
    `,
    data() {
        return {
            deskripsi : "Setengah Juve Setengah Madrid"
        }
    }
});

Di sisi halaman HTML, konten dari slot dibaca melalui <template slot-scope="dataDariKomponen">, adapun penamaan untuk slot-scope dataDariKomponen bebas diganti dengan nama apa saja.

<div class="row">

    <div class="col-md-6">
        <contoh-scoped-slots nama="Varian Hermianto">
            <template slot-scope="dataDariKomponen">
            </template>
        </contoh-scoped-slots>
    </div>
    
    <div class="col-md-6">
        <contoh-scoped-slots nama="Varian Hermianto">
            <template slot-scope="dataDariKomponen">
                <p class="card-text">Contoh Named Slots</p>
                <hr/>
                <h4 class="card-title">
                    {{ dataDariKomponen.namaProgrammer }}
                </h4>
                <p class="card-text">
                    {{ dataDariKomponen.deskripsiProgrammer }}
                </p>
                <hr/>
                <p class="card-text">
                    <strong>Kontak WA :</strong> {{ dataDariKomponen.waProgrammer }}
                </p>
            </template>
        </contoh-scoped-slots>
    </div>

</div>

Ketika template slot-scope tidak diisi dengan konten apapun, seperti di baris kode :

<div class="col-md-6">
    <contoh-scoped-slots nama="Varian Hermianto">
        <template slot-scope="dataDariKomponen">
        </template>
    </contoh-scoped-slots>
</div>

maka slot akan menampilkan nilai Konten Default, hasilnya dapat dilihat pada gambar di bawah :

penggunaan slot, named slots dan scoped slots pada vue.js