البداية · فصل ٣

مكوّن .astro من جوه

frontmatter · props · slots · Astro.props · template expressions
🎯 الهدف: تكتب مكوّن بياخد props و slot، وتفرّق كود السيرفر عن HTML اللي الزائر هيشوفه.

ملف واحد، نصين

أي .astro فيه سياج اختياري بين --- و --- اسمه frontmatter، وبعديه القالب. الكود اللي فوق السياج JavaScript أو TypeScript وبيشتغل على السيرفر: وقت البناء في الصفحات الثابتة، أو وقت الطلب لو الصفحة سيرفر. مش بيتبعت للمتصفح.

src/components/Dish.astro
---interface Props {  name: string;  price: number;  spicy?: boolean;}const { name, price, spicy = false } = Astro.props;const label = spicy ? "حار" : "عادي";---<article>  <h2>{name}</h2>  <p>{price} جنيه · {label}</p>  <slot /></article>

الأقواس {} في القالب تعبير JavaScript نتيجته تتطبع. القالب نفسه HTML، فبتكتب class مش className، ومش لازم تلف كل حاجة في عنصر أب واحد.

اللي القالب بيعمله

طباعة متغير أو نداء دالةشرط بـ && أو ternaryلف بـ map على مصفوفةمكوّنات Astro مستوردة فوقHTML عادي وتعليقات HTML
src/pages/menu.astro
---import Dish from "../components/Dish.astro";const dishes = [  { name: "كشري", price: 25 },  { name: "كشري حار", price: 30, spicy: true },];---<ul>  {dishes.map((dish) => (    <li>      <Dish name={dish.name} price={dish.price} spicy={dish.spicy}>        <p>يتقدم سخن.</p>      </Dish>    </li>  ))}</ul>

المصفوفة جوه map لازم ترجّع عنصر واحد أو Fragment. لو حابب أكتر من أخ من غير غلاف ظاهر:

src/components/Pair.astro
---import { Fragment } from "astro/jsx-runtime";---<Fragment>  <span>كشري</span>  <span>٢٥</span></Fragment>

في أغلب المكوّنات مش محتاج Fragment، لأن قالب Astro أصلًا يقبل أكتر من جذر.

الـ props والـ slots

Astro.props هو اللي الصفحة الأم بعته. عرّف interface Props عشان المحرر يلحقك لو نسيت name.

الـ slot حتة فاضية الأم تملأها. slot من غير اسم هو الافتراضي. لو سميت name="extra"، الأم تحط slot="extra" على العنصر.

Astro.slots.has("extra") يقولك الأم بعتت الحتة دي ولا لأ، عشان متطلعش صندوق فاضي. Astro.slots.render("extra") بيرندر الحتة كنص HTML لو محتاج تعمل بيها حاجة في الكود.

src/components/Dish.astro
---const { name, class: klass } = Astro.props;---<article class:list={["dish", klass, { soldout: false }]}>  {name}</article>

HTML خام وتعابير

set:html بيطبع HTML من غير تهريب. استخدمه بس لنص إنت اللي مولّده، مش لتعليق زائر. غير كده فتحت باب XSS.

set:text بيحط نص مهرب جوّه العنصر. مفيد لو عايز تمسح أطفال العنصر وتحط نص.

أي HTML جاي من بره يعتبر غير موثوق لحد ما تهربه.

فرق سريع عن JSX

JSXقالب Astro
الخاصيةclassName و camelCaseclass و kebab-case زي HTML
الجذرعنصر واحد غالبًاأكتر من عنصر عادي
التعليق{/* */}تعليق HTML، والكود فوق السياج تعليق JS
فين بيشتغلغالبًا في المتصفح كمانالقالب والـ frontmatter على السيرفر

Astro.self هو المكوّن نفسه، عشان تستدعيه من جوّاه (شجرة تعليقات أو منيو متداخل). متعملش دايرة مالهاش نهاية.

خلّصت الفصل لما

🧠 اختبر نفسك
١) فين الكود اللي فوق --- بيشتغل؟
على السيرفر، وقت البناء أو وقت الطلب. مش في المتصفح.
٢) الخاصية الصح للكلاس في قالب Astro؟
class مش className.
٣) إزاي أعرف إن الأم بعتت slot اسمه extra؟
Astro.slots.has("extra").