Slots & Composition
ทวน slot: การฉีด markup
หัวข้อที่มีชื่อว่า “ทวน slot: การฉีด markup”component มักต้องห่อ content ที่ยังไม่รู้ล่วงหน้า markup ที่ parent วางไว้ระหว่าง tag ของ component จะถูก render ตรงที่ <slot /> อยู่ — นั่นคือ default slot
---const { heading } = Astro.props;---<section class="panel"> <h2>{heading}</h2> <slot /></section><Panel heading="Notes"> <p>This paragraph lands in the default slot.</p></Panel>named slot: จุดฉีดหลายจุด
หัวข้อที่มีชื่อว่า “named slot: จุดฉีดหลายจุด”default slot อันเดียวไม่พอสำหรับ layout จริง ๆ named slot ให้ช่องที่มีป้ายชื่อหลายช่อง component ประกาศ <slot name="x" /> ส่วน parent เติมช่องเหล่านั้นด้วย slot="x" บน child
<header><slot name="header" /></header><main><slot /></main> <!-- default slot --><footer><slot name="footer" /></footer><Shell> <h1 slot="header">Page title</h1> <p>Body content fills the default slot.</p> <small slot="footer">© 2026</small></Shell>fallback content
หัวข้อที่มีชื่อว่า “fallback content”<slot> เก็บ content เริ่มต้น ที่จะ render เฉพาะตอน parent ไม่ส่งอะไรมาให้ slot นั้นได้
<button class="btn"> <slot>Click me</slot> <!-- "Click me" shows if no children are passed --></button><Button /> <!-- renders: Click me --><Button>Save</Button> <!-- renders: Save -->เช็คว่ามี slot ถูกส่งมาไหม
หัวข้อที่มีชื่อว่า “เช็คว่ามี slot ถูกส่งมาไหม”ภายใน component คุณถามได้ว่า slot ได้รับ content หรือไม่ ผ่าน Astro.slots.has แล้ว render โครงสร้างแบบมีเงื่อนไข
---const hasAside = Astro.slots.has('aside');---<div class:list={["layout", { "has-aside": hasAside }]}> <main><slot /></main> {hasAside && ( <aside><slot name="aside" /></aside> )}</div>แบบนี้ทำให้ component ปรับ markup ได้ — เช่น render wrapper aside เฉพาะตอนมี aside จะโชว์จริง ๆ เพื่อไม่ให้ปล่อย element ว่างออกมา
slot สร้าง layout
หัวข้อที่มีชื่อว่า “slot สร้าง layout”นี่คือสิ่งที่ slot มีไว้ เพื่อ ในทางปฏิบัติ layout คือ component ที่นิยาม shell ของหน้า — <html>, <head>, nav, footer — พร้อม <slot /> สำหรับ body ของหน้า ทุกหน้าห่อ content ของตัวเองใน layout ดังนั้น shell อยู่ที่เดียว
---const { title } = Astro.props;---<html lang="en"> <head> <meta charset="utf-8" /> <title>{title}</title> <slot name="head" /> </head> <body> <nav>…site nav…</nav> <main><slot /></main> <footer>…site footer…</footer> </body></html>---import BaseLayout from '../layouts/BaseLayout.astro';---<BaseLayout title="About"> <link slot="head" rel="canonical" href="https://example.com/about" /> <h1>About us</h1> <p>Page-specific content in the default slot.</p></BaseLayout>flowchart TB layout["BaseLayout: html, head, nav, footer with slots"] --> page["Page fills the default slot with its body"] page --> head["Page fills the head slot with meta tags"] layout --> out["one composed HTML document"] page --> out head --> out
รูปแบบ composition
หัวข้อที่มีชื่อว่า “รูปแบบ composition”ด้วย slot คุณประกอบ component เล็ก ๆ ให้เป็นหน้าได้แบบเดียวกับที่ประกอบฟังก์ชัน: Card ที่มี default slot สำหรับ body, Grid ที่ default slot เก็บ card, Section ที่มี named slot header และ body คุณเก็บแต่ละชิ้นให้โฟกัสแล้วให้ parent ตัดสินใจว่าจะใส่อะไรข้างใน เพราะทั้งหมด render บน server composition แทบไม่มีต้นทุนตอน runtime — เป็นแค่การประกอบ HTML เท่านั้น