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

Props & $bindable

component รับ input จาก parent ผ่าน $props() ซึ่งคุณ destructure ออกมาเป็นค่าที่คาดหวัง อันนี้แทนที่ export let ของ Svelte 4

Greeting.svelte
<script>
let { name, greeting = 'Hello' } = $props(); // name required, greeting has a default
</script>
<p>{greeting}, {name}!</p>
<!-- parent -->
<Greeting name="Ada" />
<Greeting name="Grace" greeting="Hi" />

การ destructure ให้ toolkit เต็มของ JavaScript: default (greeting = 'Hello'), rename ({ class: className }) และ rest เพื่อเก็บที่เหลือ (let { id, ...rest } = $props()) ซึ่งเหมาะกับการ forward attribute ไปยัง element ด้วย {...rest}

ด้วย lang="ts" ให้ประกาศ interface แล้ว annotate ตอน destructure — Svelte จะ type-check การใช้งานฝั่ง parent ตามนั้น

<script lang="ts">
interface Props {
name: string;
greeting?: string; // optional
count?: number;
}
let { name, greeting = 'Hello', count = 0 }: Props = $props();
</script>

props ไหล ลง: parent ส่งค่า ส่วน child อ่านค่าไปใช้ child ไม่ควร reassign prop เพื่อ “ส่งข้อมูลกลับ” นั่นทำลาย flow ทิศทางเดียว และ Svelte จะเตือน เมื่อ child ต้องสื่อสารขึ้นไป parent จะส่ง callback prop หรือทั้งคู่ share state ผ่าน binding

<script>
// Parent passes a callback; child calls it — data flows up explicitly.
let { onincrement } = $props();
</script>
<button onclick={() => onincrement()}>+1</button>

บางครั้ง two-way binding เป็น design ที่สะอาดจริง ๆ — custom input component ที่ parent อยาก bind: ค่าของตัวเอง ให้ mark prop นั้น $bindable() แล้ว parent จะ bind ได้

FancyInput.svelte
<script>
let { value = $bindable() } = $props();
</script>
<input bind:value={value} />
<!-- parent -->
<script>
let name = $state('');
</script>
<FancyInput bind:value={name} /> <!-- two-way: parent's name stays in sync -->
flowchart TB
  parent["Parent state"] -->|props ไหลลง| child["Child อ่าน props"]
  child -->|callback prop| parent
  parent <-->|bind: ด้วย $bindable| child
props ไหลลง; $bindable เปิด channel สองทาง

two-way binding เป็น opt-in โดยตั้งใจ: prop ส่วนใหญ่ยังเป็นทางเดียว (reason ง่ายกว่า) และ $bindable เก็บไว้สำหรับ component ที่การ sync ค่าทั้งสองทางเป็น interface ที่เป็นธรรมชาติ

component ใน Svelte 5 ประกาศ props ยังไง?
ให้ default value กับ prop ยังไง?
โดย default ข้อมูลไหลยังไงกับ props?
จะให้ parent `bind:` กับ prop ของ child ยังไง?