Slots
React ส่ง children ผ่าน prop ชื่อ children ส่วน Astro ใช้ <slot /> ที่เป็นแนวคิดของ Web Component ที่สร้างไว้ใน template เลย ผลลัพธ์เหมือนกัน: parent เป็นคนตัดสินใจว่าจะใส่อะไรเข้าไปข้างใน ส่วน component เป็นคนตัดสินใจว่าจะวางเนื้อหานั้นไว้ตรงไหน
Default slot (ตัวเทียบเท่าของ children)
หัวข้อที่มีชื่อว่า “Default slot (ตัวเทียบเท่าของ children)”// Card.jsxexport default function Card({ children }) { return ( <div className="card"> {children} </div> );}
// Usage:// <Card>// <h2>Title</h2>// <p>Body text</p>// </Card>---// Card.astro---<div class="card"> <slot /></div>
<!-- Usage:<Card> <h2>Title</h2> <p>Body text</p></Card>-->ไม่ต้องประกาศ prop ใด ๆ — <slot /> จะรับ children ที่ส่งเข้ามาให้ component โดยอัตโนมัติ ถ้าไม่มี children ถูกส่งเข้ามา slot จะไม่ render อะไรเลย (คุณสามารถใส่ fallback content ไว้ระหว่าง tag ของ slot ได้: <slot>Default content</slot>)
Named slots
หัวข้อที่มีชื่อว่า “Named slots”React ไม่มี named slot ในตัว pattern ที่ใช้กันทั่วไปคือ render props, compound component หรือ prop แยกอย่าง header={<H1 />} ส่วน Astro มี named slot แบบ first-class
ใน นิยามของ component ให้วาง <slot name="header" /> ตรงตำแหน่งที่คุณต้องการให้ content ของ header ปรากฏ
ใน การใช้งาน component ให้เพิ่ม slot="header" ลงใน child element ใด ๆ เพื่อส่งไปยัง slot นั้น
// Layout.jsx — React named-slot workaroundexport default function Layout({ header, sidebar, children }) { return ( <div className="layout"> <header>{header}</header> <aside>{sidebar}</aside> <main>{children}</main> </div> );}
// Usage:// <Layout// header={<nav>Nav here</nav>}// sidebar={<ul>Links</ul>}// >// <p>Main content</p>// </Layout>---// Layout.astro---<div class="layout"> <header><slot name="header" /></header> <aside><slot name="sidebar" /></aside> <main><slot /></main></div>
<!-- Usage:<Layout> <nav slot="header">Nav here</nav> <ul slot="sidebar">Links</ul> <p>Main content</p></Layout>-->ตัวอย่างที่รันได้จริง
หัวข้อที่มีชื่อว่า “ตัวอย่างที่รันได้จริง”---
// No frontmatter needed for this demo
---
<html lang="en">
<head><meta charset="utf-8" /><title>Slots demo</title></head>
<body style="font-family:sans-serif;padding:2rem;max-width:600px;margin:auto">
<style>
.card { border:1px solid #e2e8f0; border-radius:8px; overflow:hidden; }
.card header { background:#6366f1; color:#fff; padding:1rem; }
.card main { padding:1rem; }
.card footer { background:#f8fafc; padding:.75rem 1rem; font-size:.875rem; color:#64748b; }
</style>
<!-- Inline component demo using an HTML template pattern -->
<div class="card">
<header>
<h2>Named Slots</h2>
</header>
<main>
<p>The default slot receives children with no slot attribute.</p>
<p>Named slots receive children tagged with slot="name".</p>
</main>
<footer>No JavaScript required.</footer>
</div>
</body>
</html>