Special Elements — Svelte

Svelte menyediakan elemen khusus dengan prefix svelte: untuk fitur lanjutan. svelte:component import Red from "./Red.svelte" import Blue from "./Blue.svelte"…

Elemen khusus Svelte adalah tag berawalan svelte: yang bukan elemen HTML. Mereka memberi komponen akses ke hal yang gak bisa ditulis sebagai markup biasa: jendela browser (<svelte:window>), bagian <head> halaman (<svelte:head>), komponen atau tag yang baru dipilih saat aplikasi jalan (<svelte:component>, <svelte:element>), dan komponen itu sendiri (<svelte:self>). Bayangin bangunan Warung Bu Sri. Dagangan di meja itu elemen HTML biasa. Tapi dari dalam, Bu Sri juga bisa melihat keluar jendela, mengganti tulisan di papan nama di atas pintu, menukar etalase di tempat yang sama, dan menata rak bertingkat yang tiap tingkatnya rak dengan bentuk yang sama. Itu bukan dagangan; itu bagian bangunan yang dia atur dari dalam.

🧪 Tebakan cepat: kode awal latihan punya let innerWidth. Kalau kamu langsung menulis <p>Lebar: {innerWidth}px</p> tanpa <svelte:window>, paragrafnya membaca apa: lebar jendela, Lebar: 0px, atau Lebar: undefinedpx? Jawabannya ada di bagian "svelte:window: jendela browser".

svelte:window: jendela browser

<script>
  let lebar
  let scrollY = 0
  let buka = false

  function tekan(event) {
    if (event.key === "Escape") buka = false
  }
</script>

<svelte:window bind:innerWidth={lebar} bind:scrollY on:keydown={tekan} />

<p>Lebar: {lebar}px</p>
<button class:mengambang={scrollY > 80} on:click={() => (buka = true)}>Keranjang (3)</button>

Hasilnya dari Svelte 4:

Kejadian Nilai di komponen Yang tampil
dibuka di jendela 1.024 px lebar = 1024 Lebar: 1024px
jendela dikecilkan jadi 375 px lebar = 375 Lebar: 375px
halaman digulir 120 px scrollY = 120 tombol Keranjang mengambang
tombol Escape ditekan buka = false dropdown keranjang tertutup

Dua aturan, dengan pesan compiler-nya: <svelte:window> harus di tingkat teratas komponen (di dalam {#if} ditolak dengan <svelte:window> tags cannot be inside elements or blocks), dan cuma boleh satu per komponen (A component can only have one <svelte:window> tag). Untuk event di document atau <body>, ada <svelte:document> dan <svelte:body> dengan aturan yang sama.

svelte:head: judul di tab browser

<svelte:head>
  <title>Keranjang ({keranjang.length}) · Warung Bu Sri</title>
</svelte:head>

Isi <svelte:head> dipindah ke <head> dokumen. Dengan dua menu di keranjang, tab browser membaca Keranjang (2) · Warung Bu Sri; tambah satu, jadi Keranjang (3) · Warung Bu Sri. Tempat yang cocok untuk <title> dan <meta name="description">. Di SvelteKit, isinya ikut dirender di server, jadi mesin pencari langsung melihat judulnya. Aturannya sama: hanya di tingkat teratas komponen.

svelte:component: pilih komponen saat jalan

<script>
  import DaftarList from "./DaftarList.svelte"
  import DaftarGrid from "./DaftarGrid.svelte"

  export let menu
  let lebar

  $: tampilan = lebar < 600 ? DaftarList : DaftarGrid
</script>

<svelte:window bind:innerWidth={lebar} />

<svelte:component this={tampilan} {menu} />

svelte:element: pilih tag saat jalan

<svelte:element this={tag}>Menu</svelte:element> merender <h2>Menu</h2> saat tag = "h2", dan <p>Menu</p> saat tag = "p". Bedanya dengan svelte:component: this di sini berisi nama tag HTML sebagai string.

svelte:self: komponen di dalam dirinya sendiri

Kategori menu warung bertingkat: Menu berisi Makanan dan Minuman, Makanan berisi Nasi Goreng dan Mie Ayam. Tiap tingkat bentuknya sama, jadi satu komponen bisa memasang dirinya sendiri untuk anak-anaknya:

<!-- Kategori.svelte -->
<script>
  export let simpul
</script>

<li>
  {simpul.nama}
  {#if simpul.anak.length > 0}
    <ul>
      {#each simpul.anak as anak}
        <svelte:self simpul={anak} />
      {/each}
    </ul>
  {/if}
</li>

Dengan { nama: "Menu", anak: [Makanan, Minuman] }, hasilnya daftar bertingkat: Menu, di dalamnya Makanan (Nasi Goreng, Mie Ayam) dan Minuman (Es Teh). Rekursinya berhenti di simpul yang anak-nya kosong. Karena itu <svelte:self> wajib berada di dalam {#if}, {#each}, atau slot; di tingkat teratas, compiler menolak dengan <svelte:self> components can only exist inside {#if} blocks, {#each} blocks, or slots passed to components, supaya gak terjadi rekursi tanpa akhir.

Svelte 5

<svelte:window>, <svelte:head>, <svelte:element>, <svelte:document>, dan <svelte:body> tetap sama; event-nya ditulis onkeydown. Dua yang lain sudah usang di mode runes. Komponen di Svelte 5 dinamis dengan sendirinya: let Tampilan = $derived(lebar < 600 ? DaftarList : DaftarGrid) lalu <Tampilan {menu} />, dan compiler memberi warning svelte_component_deprecated untuk <svelte:component>. Untuk rekursi, file-nya mengimpor dirinya sendiri: import Kategori from "./Kategori.svelte", dengan warning svelte_self_deprecated untuk <svelte:self>.

⚠️ Jebakan yang sering ketemu

TL;DR: Tag svelte: memberi komponen akses ke bagian di luar markup biasanya. <svelte:window bind:innerWidth={lebar} bind:scrollY on:keydown={tekan} /> mengikat ukuran dan posisi gulir jendela (scrollX/scrollY dua arah, sisanya cuma dibaca) dan mendengarkan event tanpa perlu membereskan listener sendiri; tanpa binding, innerWidth cuma undefined. <svelte:head> mengisi <head>, misalnya <title>Keranjang (3) · Warung Bu Sri</title>. <svelte:component this={tampilan} /> memasang komponen yang dipilih saat jalan dan menghancurkan yang lama; this={null} gak merender apa-apa. <svelte:element this={tag}> memilih tag HTML, dan <svelte:self> memasang komponen itu sendiri untuk data bertingkat, wajib di dalam {#if} atau {#each}. svelte:window dan svelte:head cuma di tingkat teratas, satu window per komponen. Di Svelte 5, <svelte:component> dan <svelte:self> usang: komponen sudah dinamis, dan file bisa mengimpor dirinya. Latihannya: <svelte:window bind:innerWidth /> dan <p>Lebar: {innerWidth}px</p>.

Yang akan kamu pelajari