ข้ามไปยังเนื้อหา

Snippets & Render

snippet คือ block ของ markup ที่มีชื่อ ซึ่ง render ซ้ำได้หลายครั้ง นิยามด้วย {#snippet name(params)}…{/snippet} และ render ด้วย {@render name(args)} เป็นวิธีของ Svelte ที่ทำให้ template DRY

<script>
let items = $state([
{ name: 'Coffee', price: 3 },
{ name: 'Tea', price: 2 },
]);
</script>
{#snippet row(item)}
<tr><td>{item.name}</td><td>${item.price}</td></tr>
{/snippet}
<table>
{#each items as item (item.name)}
{@render row(item)}
{/each}
</table>

snippet row นิยามครั้งเดียวและ render ต่อ item แต่ละตัว snippet รับ พารามิเตอร์ ได้เหมือนฟังก์ชัน markup เดียวกันจึงปรับตามข้อมูลที่ต่างกันได้

flowchart LR
  def["snippet row(item) ... end"] --> render1["render row(a)"]
  def --> render2["render row(b)"]
  render1 --> out["instance ของ markup"]
  render2 --> out
นิยามครั้งเดียว render หลายครั้ง

ใน Svelte 4 เราส่ง markup เข้า component ด้วย <slot> (และ named slot ผ่าน <slot name="x">) Svelte 5 แทนที่สิ่งนั้นทั้งหมดด้วย snippets — ซึ่งทรงพลังกว่าเพราะรับพารามิเตอร์ได้และเป็นแค่ค่าที่ส่งไปมาได้

<!-- Svelte 4 (เดิม): component นิยาม <slot /> และ <slot name="header" /> -->
<!-- Svelte 5 (ใหม่): component render {@render children()} และ {@render header()} -->

ถ้าคุณอ่าน tutorial เก่าที่ใช้ <slot> ตัวเทียบเท่าสมัยใหม่คือ snippet ที่ render ด้วย {@render} บทถัดไปจะอธิบายว่า parent ส่ง snippet (รวมถึง children snippet พิเศษ) เข้า child อย่างไร

เพราะ snippet เป็นค่า คุณจึงส่ง snippet ไปให้ snippet อื่น เก็บใน variable หรือเลือกระหว่าง snippet แบบมีเงื่อนไขได้:

{#snippet loading()}<p>Loading…</p>{/snippet}
{#snippet ready(data)}<p>{data}</p>{/snippet}
{#if isLoading}
{@render loading()}
{:else}
{@render ready(result)}
{/if}

ความ composable นี้ — snippet เป็น first-class value ที่รับพารามิเตอร์ได้ — คือเหตุผลที่มาแทนกลไก slot ที่ยืดหยุ่นน้อยกว่า

นิยามและ render snippet ยังไง?
snippet มาแทนอะไรใน Svelte 5?
ทำไม snippet ถึงทรงพลังกว่า slot?
snippet รับพารามิเตอร์ได้ไหม?