Komponen adalah potongan tampilan yang ditulis sekali lalu bisa dipasang berkali-kali. Di Svelte, satu komponen adalah satu file .svelte. Bayangin stempel Warung Bu Sri. Stempelnya diukir sekali, lalu dicap di tiap nota, dan tiap cap hasilnya sama. Tintanya cuma menempel di bagian yang kena stempel, gak meluber ke tulisan lain di nota. Komponen bekerja persis begitu: file-nya stempel, tiap <MenuItem /> satu kali cap, dan style di dalam komponen adalah tinta yang cuma mengenai bagian komponen itu.
🧪 Tebakan cepat:
MenuItem.sveltepunya stylep { color: #c2410c; }(oranye).App.sveltepunya paragrafnya sendiri,<p>Buka setiap hari, 07.00 sampai 21.00.</p>, lalu memasang<MenuItem />. Paragraf mana yang jadi oranye: cuma yang di dalam MenuItem, atau paragraf App juga? Jawabannya ada di bagian "Style yang scoped".
Satu file, tiga bagian
Ini kartu menu Warung Bu Sri sebagai komponen, di file MenuItem.svelte:
<script>
let nama = "Nasi Goreng"
let harga = 15000
</script>
<h3>{nama}</h3>
<p>Rp {harga.toLocaleString("id-ID")}</p>
<style>
p {
color: #c2410c;
font-weight: bold;
}
</style>
<script>berisi logika: variabel, fungsi, import.- Markup di tengah adalah tampilannya, HTML plus kurung kurawal.
<style>berisi CSS khusus komponen ini.- Ketiganya opsional. File yang isinya cuma markup tetap komponen yang sah. Urutan yang lazim: script, markup, style.
- Nama file jadi nama komponennya:
MenuItem.svelteadalah komponenMenuItem. Namanya ditulis PascalCase, tiap kata diawali huruf kapital.
Memakai komponen di komponen lain
Komponen dipasang dengan mengimpornya di <script>, lalu menulisnya seperti tag. Ini App.svelte, komponen paling luar aplikasinya:
<script>
import MenuItem from "./MenuItem.svelte"
</script>
<h1>Warung Bu Sri</h1>
<p>Buka setiap hari, 07.00 sampai 21.00.</p>
<MenuItem />
<MenuItem />
<MenuItem />
import MenuItem from "./MenuItem.svelte": path ke file-nya, lengkap dengan.svelte../artinya folder yang sama. Pola yang sama berlaku untuk komponen apa pun, misalnyaimport Greeting from "./Greeting.svelte".<MenuItem />memasang satu salinan. Tiga baris, tiga kartu. Di kode hasil compile-nya adanew MenuItem({})tiga kali.- Ketiga kartunya sama persis, semuanya "Nasi Goreng". Membuat tiap salinan punya isi sendiri adalah tugas props, di pelajaran berikutnya.
Hasilnya di halaman: judul Warung Bu Sri, paragraf jam buka, lalu tiga pasang <h3>Nasi Goreng</h3> dan <p>Rp 15.000</p>.
Style yang scoped
Style di komponen Svelte otomatis scoped: cuma berlaku untuk elemen milik komponen itu. Compiler melakukannya dengan memberi class unik. Dari MenuItem.svelte tadi, Svelte menghasilkan:
p.svelte-n0sg1r{color:#c2410c;font-weight:bold}
<h1>Warung Bu Sri</h1>
<p>Buka setiap hari, 07.00 sampai 21.00.</p>
<h3>Nasi Goreng</h3>
<p class="svelte-n0sg1r">Rp 15.000</p>
svelte-n0sg1radalah class yang dibuat compiler dari isi style-nya. Selektorpdiubah jadip.svelte-n0sg1r.- Class itu cuma ditempel ke
<p>yang ditulis diMenuItem.svelte.<h3>gak dapat class karena gak ada style untuknya. - Paragraf jam buka ditulis di
App.svelte, jadi gak punya class itu dan tetap hitam.
Jadi yang oranye cuma paragraf harga di dalam MenuItem. Itu jawaban tebakannya. Berlaku dua arah: style p di App.svelte juga gak mengenai paragraf di dalam MenuItem, karena App dapat class-nya sendiri (svelte-5kgbet).
Kalau style-nya menyebut elemen yang gak ada di komponen itu, misalnya h1 { color: red; } di MenuItem, compiler memberi warning Unused CSS selector "h1" dan membuang aturannya.
Latihan: komponen pertamamu
Latihan pelajaran ini satu komponen dengan markup saja. Kode awalnya cuma komentar. Ganti dengan:
<h1>Hyper Sheets</h1>
<p>Belajar Svelte itu seru!</p>
<h1> berisi Hyper Sheets dan <p> berisi Belajar Svelte itu seru!, persis dengan tanda serunya. Gak butuh <script> atau <style>.
Svelte 4 dan Svelte 5
Struktur file, import, dan cara memasang <MenuItem /> sama persis di dua versi. Bedanya cuma di cara komponen paling luar dipasang ke halaman, di file main.js: Svelte 4 menulis new App({ target: document.getElementById("app") }), Svelte 5 menulis mount(App, { target: document.getElementById("app") }). Kalau pakai SvelteKit, bagian itu sudah diurus untukmu.
⚠️ Jebakan yang sering ketemu
- Nama komponen huruf kecil.
<menuItem />dianggap tag HTML biasa, bukan komponen, jadi kartunya gak muncul. Compiler memberi warning:<menuItem> will be treated as an HTML element unless it begins with a capital letter. Nama komponen selalu diawali huruf kapital. - Lupa
.sveltedi path import.import MenuItem from "./MenuItem"gagal ditemukan saat build. Tulis lengkap:"./MenuItem.svelte". - Mengira style App mengenai isi komponen anak. Style scoped berlaku dua arah. Untuk mengatur tampilan komponen anak, tulis style-nya di file anak itu sendiri.
- Dua komponen di satu file. Satu file
.svelteselalu satu komponen. Kartu menu dan keranjang jadi dua file.
TL;DR: Satu file .svelte adalah satu komponen, dengan tiga bagian opsional: <script> untuk logika, markup untuk tampilan, <style> untuk CSS. Komponen dipakai dengan import MenuItem from "./MenuItem.svelte" lalu <MenuItem />, sebanyak yang kamu mau. Namanya PascalCase, karena <menuItem /> huruf kecil dianggap tag HTML. Style di komponen otomatis scoped: compiler menambah class seperti svelte-n0sg1r ke elemen milik komponen itu saja, jadi style gak bocor keluar dan gak masuk dari luar.