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

Snippets & Children

React ส่งเนื้อหา UI ให้ component ผ่าน children (JSX ที่อยู่ระหว่าง tag) หรือ render props (function ที่ return JSX) ส่วน Svelte 5 แทนที่ระบบ <slot> แบบเก่าด้วย snippets — ชิ้นส่วน template ที่นำกลับมาใช้ซ้ำได้ มีชื่อ และรับ parameter ได้ นิยามด้วย {#snippet} และ render ด้วย {@render} snippet ตัว default ยังคงชื่อ children อยู่ ดังนั้นการใช้งานพื้นฐานจึงรู้สึกคุ้นเคยทันที

React
// Card.jsx
function Card({ children }) {
return <div className="card">{children}</div>;
}
// Usage:
<Card>
<p>Hello from inside!</p>
</Card>
Svelte
<!-- Card.svelte -->
<script>
let { children } = $props();
</script>
<div class="card">
{@render children()}
</div>
<!-- Usage in parent: -->
<!-- <Card><p>Hello from inside!</p></Card> -->

prop children คือ snippet function — คุณต้องเรียกด้วย {@render children()} ส่วน {children} ของ React เป็นค่า (value) แต่ children ของ Svelte เป็น snippet ที่เรียกได้ (callable)

React
// Dialog.jsx
function Dialog({ header, body, footer }) {
return (
<div className="dialog">
<div className="dialog-header">{header}</div>
<div className="dialog-body">{body}</div>
<div className="dialog-footer">{footer}</div>
</div>
);
}
// Usage:
<Dialog
header={<h2>Confirm</h2>}
body={<p>Are you sure?</p>}
footer={<button>OK</button>}
/>
Svelte
<!-- Dialog.svelte -->
<script>
let { header, body, footer } = $props();
</script>
<div class="dialog">
<div class="dialog-header">{@render header()}</div>
<div class="dialog-body">{@render body()}</div>
<div class="dialog-footer">{@render footer()}</div>
</div>
<!-- Usage in parent: -->
<!--
<Dialog>
{#snippet header()}<h2>Confirm</h2>{/snippet}
{#snippet body()}<p>Are you sure?</p>{/snippet}
{#snippet footer()}<button>OK</button>{/snippet}
</Dialog>
-->

snippet รับ argument ได้ — สิ่งนี้แทนที่แพตเทิร์น render-prop ของ React ได้อย่างสะอาดสะอ้าน:

React
// List.jsx
function List({ items, renderItem }) {
return (
<ul>
{items.map((item, i) => (
<li key={i}>{renderItem(item)}</li>
))}
</ul>
);
}
// Usage:
<List
items={fruits}
renderItem={fruit => <strong>{fruit}</strong>}
/>
Svelte
<!-- List.svelte -->
<script>
let { items, renderItem } = $props();
</script>
<ul>
{#each items as item}
<li>{@render renderItem(item)}</li>
{/each}
</ul>
<!-- Usage in parent:
<List {items}>
{#snippet renderItem(fruit)}
<strong>{fruit}</strong>
{/snippet}
</List>
-->
คุณ render default children ใน Svelte 5 component อย่างไร?
syntax ของ Svelte 5 สำหรับนิยามชิ้นส่วน template ที่นำกลับมาใช้ซ้ำได้พร้อม parameter คืออะไร?
อะไรมาแทนที่ named slot ของ Svelte 4 ใน Svelte 5?