Emmet: الصعود `^` والضرب `*`: هياكل شجرية معقدة وعناصر متكررة
غطى الدرس السابق "النزول" بـ
>و"الجعل مسطحًا" بـ+. عندما يصبح هيكلك معقدًا بما يكفي بحيث "يحتاج أخ إلى العودة للأعلى مستوى"، يواجه هذان العاملان وحدهما حائطًا — هنا تحتاج^للصعود مستوى واحدًا. لإنشاء 5 أو 10 أو أكثر من العناصر المتطابقة دفعة واحدة، استخدم*للتكرار.
1. ما ستتعلمه
- دلالات عامل الصعود
^: "اقفز للخارج" من مستوى التداخل الحالي بمقدار واحد - الصعود متعدد المستويات
^^^: اقفز لأعلى عدة مستويات متتالية للوصول إلى السياقات الخارجية - دلالات عامل الضرب
*N: كرر العنصر السابق N مرة - كيف يعمل
*Nو>معًا:>يغير السياق،*Nينطبق على المستوى الحالي - دمج هياكل شجرية معقدة: نمط "ابق عميقًا، اصعد إلى المستوى المحدد" مع الأقواس
2. قصة حقيقية لمطور واجهة أمامية
(1) نقطة الألم: التداخل متعدد المستويات والوقوع "عالقًا عميقًا"
تعيد أليس هيكلة صفحة رئيسية لمتجر إلكتروني، محولة تخطيطًا مسطحًا إلى هيكل HTML5 ثلاثي الأقسام دلالي (header + main + footer). تستخدم body>header+main+footer من الدرس السابق للطبقة الخارجية، ثم تنزل داخل header بـ >nav>ul>li*5>a. لكن بعد إنهاء قسم header، تظهر مشكلة: يجب أن يتبع footer main كأخ، لكنها تجد footer ينتهي داخل header — لأن > يستمر في دفع السياق أعمق وأعمق، و + فقط يلحق في أحدث مستوى.
الأسوأ، تحتاج إلى بناء جدول منتجات بـ 6 صفوف × 5 أعمدة. 6 صفوف بـ *6 لا مشكلة، لكن كل صف يحتاج إلى 5 خلايا td مكررة — كتابة 30 عنصر td يدويًا تعني إما إعادة الكتابة أو كتابة tr>td*5*6 طويلة وصعبة القراءة. تتساءل أليس: ليت * يمكنه التداخل داخل * بشكل صحيح.
(2) كيف يحلها ^ و *
يوفر Emmet عاملين متكاملين لحل كلتا المشكلتين:
الصعود ^: عندما تنتهي من الكتابة عميقًا داخل header وتريد القفز مرة أخرى إلى مستوى body لإلحاق footer، ^ "يصعد للخارج" مستوى واحدًا، عائدًا إلى موضع أخ الأصل. تحتاج أليس فقط إلى إضافة ^ في نهاية شجرة header الفرعية، ثم إلحاق main+footer:
body>header>nav>ul>li*5>a^^main+footer
^^ يصعد مستويين لأعلى من داخل ul (أولاً خارج ul، ثم خارج nav، عائدًا إلى مستوى header)، لذا +main+footer يصبحان أخوة لـ header.
ا��ضرب *: يمكن وضع * في Emmet بعد أي عنصر لتكراره N مرة — و * يمكنه تداخل > داخله لتشكيل هياكل فرعية. جدول كامل هو سطر واحد:
table>(tr>td*5)*6
tr>td*5 هو "نمط صف"، مغلف بـ *6 لتكرار النمط 6 مرات. من 30 عنصر td إلى سطر اختصار واحد — من 5 دقائق إلى 8 ثوانٍ.
(3) الفوائد
^ و * هما التركيبة الأساسية لمعالجة "الهياكل المعقدة" في Emmet. الصعود يتيح لك التحكم بدقة في المستوى الذي ينتمي إليه كل عنصر؛ الضرب يتيح لك توليد هياكل متكررة دفعة واحدة في سطر واحد. بعد هذا الدرس، تجمع أليس body>header+main+footer مع ^^^ للتحكم المثالي في المستوى وتكتب جدول 6×5 بـ * في سطر واحد — من 12 دقيقة إلى 25 ثانية. التجميع () في الدرس التالي سيجعل هذه العوامل أقوى عند دمجها.
3. عامل الصعود ^: العودة إلى مستوى الأصل
^ تعني اصعد لأعلى — حرك موضع العناصر اللاحقة للخلف من المستوى الحالي إلى مستوى الأصل. يعالج سيناريو شائعًا: أنهيت شجرة فرعية عميقًا داخل هيكل متداخل وتريد أن يكون العنصر التالي أخًا لـ "جد" بدلاً من البقاء محاصرًا في المستوى الحالي.
| الصيغة | المعنى |
|---|---|
^ |
اصعد مستوى واحدًا (للخلف مستوى سياق واحد) |
^^^ |
اصعد 3 مستويات |
^bq مكافئ لـ +bq في مستوى الأصل |
اصعد وألحق عنصرًا فورًا |
(1) توضيح الصعود الفردي
| جزء الاختصار | الشكل | الفرق الرئيسي |
|---|---|---|
div+div>p>span+em^bq |
bq هو أخ لـ p (داخل div الثاني) |
^ يشغل الصعود |
div+div>p>span+em+bq |
bq هو أخ لـ span و em (داخل p) |
بدون ^، لا يزال في مستوى p |
نقطة أساسية: الصعود هو أحد أكثر عوامل Emmet إرباكًا للمبتدئين. "السياق السابق" يشير إلى العقدة الأصلية في شجرة الصياغة، وليس "آخر عنصر كتبته." بعبارة أخرى، في
div>ul>li^p،^يجعلpأخًا لـul(كلاهما داخل div)، وليس أخًا لـli(داخل li).
4. عامل الضرب *: تكرار العناصر دفعة واحدة
*N تعني كرر — ضاعف العنصر السابق N مرة. هذا هو العامل الأساسي لـ Emmet لمعالجة الهياكل المتكررة مثل "N عنصر قائمة،" "N صف جدول،" و "N بطاقة."
| الصيغة | المعنى |
|---|---|
li*5 |
5 عناصر li |
div.card*3 |
3 عناصر div.card (div ضمني، الدرس 3) |
tr>td*6 |
tr واحد يحتوي على 6 td |
(tr>td*6)*5 |
5 tr، كل منها يحتوي على 6 td (تجميع، الدرس 6) |
نصيحة: N في
*Nيجب أن يكون عددًا صحيحًا موجبًا.*1صالح (مكافئ لعدم التكرار) لكن عادة يُبسط إلى الصيغة المفردة.*0في Emmet يتوسع إلى لا شيء (لا يولد عناصر).
(1) نطاق الضرب
* ينطبق فقط على العنصر السابق مباشرة، متبعًا قاعدة "السياق المحلي". لتكرار شجرة فرعية متداخلة كاملة كوحدة، يجب استخدام الأقواس () للتجميع (الدرس 6):
| الاختصار | نطاق التكرار | استخدام خاطئ (محاولة التكرار ككل بدون أقواس) |
|---|---|---|
ul>li*3 |
3 li | — |
ul>li*3>a |
3 li، كل منها يحتوي على a واحد | — |
tr>td*5*6 |
فقط 5 td؛ *6 يكرر tr ككل (Emmet يحلل كـ 5 td إجمالاً، tr مكرر 6 مرات) |
"لـ 6 صفوف × 5 أعمدة" استخدم (tr>td*5)*6 |
5. أمثلة عملية
تغطي الأمثلة الخمسة التالية جميع السيناريوهات الأساسية لـ ^ و * — من الصعود الفردي إلى الصعود متعدد المستويات، من التكرار البسيط إلى التكرار المجمع المتداخل.
▶ مثال: صعود فردي div+div>p>span+em^bq (الصعوبة: ★★)
المشكلة المتبقية من الدرس السابق: كيفية جعل bq أخًا لـ p. الإجابة هي إضافة ^.
الاختصار:
div+div>p>span+em^bq
يتوسع إلى:
<div></div>
<div>
<p><span></span><em></em></p>
<blockquote></blockquote>
</div>
الناتج:
TEXT 📖 للعرض فقطالتحليل: div+div ينشئ divين أخوين، >p ينزل داخل div الثاني لوضع p، >span+em يضع أخوين داخل p. أخيرًا، ^ يشغل صعودًا: من مستوى p لأعلى إلى مستوى div (أصل p)، لذا bq يصبح أخًا لـ p — كلاهما أبناء لـ div الثاني. بدون ^، سينتهي bq داخل p، أخًا لـ span و em.
▶ مثال: صعود متعدد المستويات div+div>p>span+em^^^bq (الصعوبة: ★★)
ثلاث ^ متتالية تصعد طوال الطريق إلى مستوى الجذر.
الاختصار:
div+div>p>span+em^^^bq
يتوسع إلى:
<div></div>
<div>
<p><span></span><em></em></p>
</div>
<blockquote></blockquote>
الناتج:
TEXT 📖 للعرض فقط`^^^` يصعد ثلاث مرات: الأولى من p إلى div الثاني، الثانية من div الثاني إلى الجذر، الثالثة تحاول مجددًا من الجذر لكن لا يوجد "مستوى أعلى" (تبقى في مكانها). لذا bq ينتهي كأخ لـ div الثاني، ابنًا مباشرًا للجذر. ملاحظة: مستوى الجذر ليس له حاوية صريحة (لا يوجد div أبعد)، لذا bq يظهر بجانب div. هذا "الاختصار بدون جذر" يُغلف تلقائيًا بـ `<body>` في المتصفحات، لكن كن واعيًا لكيفية تأثير تغييرات المستوى على محددات CSS اللاحقة.
▶ مثال: الضرب ul>li*5 (الصعوبة: ★)
أبسط "توليد دفعة لـ 5 عناصر li."
الاختصار:
ul>li*5
يتوسع إلى:
<ul>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
</ul>
الناتج:
TEXT 📖 للعرض فقط5 عناصر li فارغة، جميعها أبناء مباشرون لـ ul. `*5` يعمل مباشرة على li — لا حاجة لهيكل معقد. هذا هو نمط Emmet الأعلى ترددًا لـ "قائمة تنقل بـ 5 عناصر،" "قائمة مهام بـ 5 عناصر،" "5 بطاقات ميزات،" وسيناريوهات مماثلة. اقرن مع ملء المحتوى (الدرس 9) لإعطاء كل عنصر نصًا مختلفًا.
▶ مثال: تكرار + تداخل ul>li*3>a (الصعوبة: ★)
التركيبة الكلاسيكية > + * — a كالابن الوحيد لكل li.
الاختصار:
ul>li*3>a
يتوسع إلى:
<ul>
<li><a href=""></a></li>
<li><a href=""></a></li>
<li><a href=""></a></li>
</ul>
الناتج:
TEXT 📖 للعرض فقط`*3` يكرر li فقط، وكل li يحتوي على a واحد عبر >. لتكرار a أيضًا (3 a لكل li)، استخدم الأقواس: ul>li*>a*3 أو غلف a في مجموعة. لتكرار "(li و a)" كوحدة، استخدم (li>a)*3 (الدرس 6، التجميع). هذا فخ "نطاق" كلاسيكي في Emmet.
▶ مثال: مجموعة + تكرار (div>dl>(dt+dd)*3)+footer>p (الصعوبة: ★★)
المثال المدمج لهذا الدرس: ضرب متداخل + تجميع (() من الدرس 6 — معاينة هنا).
الاختصار:
(div>dl>(dt+dd)*3)+footer>p
يتوسع إلى:
<div>
<dl>
<dt></dt>
<dd></dd>
<dt></dt>
<dd></dd>
<dt></dt>
<dd></dd>
</dl>
</div>
<footer>
<p></p>
</footer>
الناتج:
TEXT 📖 للعرض فقطالتحليل: الأبعد (div>dl>...) يعمل كمجموعة، ويعمل "كجذر افتراضي." داخل المجموعة، div يحتوي على dl، و (dt+dd)*3 داخل dl يكرر زوج الأخوة dt+dd 3 مرات. ثم + يجعل footer أخًا لـ div (footer هو شجرة فرعية منفصلة ومستقلة)، و >p داخل footer يضع p. سطر الاختصار الكامل يتوسع إلى 13 سطرًا من HTML: 1 dl، 6 dt/dd، 1 footer، 1 p. هذا هو نمط Emmet النموذجي لكتابة كتلة قائمة تعريفات في سطر واحد.
6. مثال كامل: جد��ل منتجات 6×5
استخدم * المتداخل والتجميع لبناء جدول منتجات بـ 6 صفوف و 5 أعمدة بسطر اختصار واحد.
▶ مثال: جدول منتجات 6×5 (الصعوبة: ★★)
الاختصار:
table>(tr>td*5)*6
يتوسع إلى:
<table>
<tr>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
</table>
الناتج:
TEXT 📖 للعرض فقطالتحليل: tr>td*5 هو قالب "صف واحد من الخلايا،" و *6 الخارجي يكرر هذا القالب 6 مرات. الأقواس (tr>td*5) تضمن أن td*5 ينطبق فقط داخل tr (5 td كلها في نفس tr)، بدلاً من أن يتكرر مباشرة بواسطة *6 الخارجي. عاملا * متداخلان يشكلان شبكة ثنائية الأبعاد. بدون أقواس، tr>td*5*6 سيظل ينتج نتيجة 6×5 (Emmet يحلله كـ 5 td لكل tr، tr مكرر 6 مرات)، لكن الدلالات غير واضحة — لا يُنصح به.
❓ أسئلة شائعة
^، كيف كان الناس يتعاملون مع احتياجات الصعود؟div>header>p+span^(main+footer) لم يكن موجودًا؛ كنت ستكتب (header>p+span)+(main+footer) باستخدام التجميع كحل بديل. لكن التجميع أقل قابلية للقراءة ويتطلب إعادة النزول. أضيف ^ في 2013 كـ "فتحة هروب" خصيصًا لحل نقطة الألم هذه.^ الصعود طوال الطريق إلى الجذر؟ ماذا يحدث إذا صعدت بعيدًا جدًا؟^^^^^bq في مستوى الجذر) يبقى فقط في الجذر — لا خطأ. يعامل Emmet الجذر كـ "الطابق الأرضي،" ويتم تجاهل رموز ^ الزائدة بصمت.li*0؟*0 في Emmet الرسمي يولد 0 عناصر (متخطى تمامًا)، لكن بعض تطبيقات المحررات قد تترك عنصر li فارغًا واحدًا. تجنب كتابة *0 — فقط اكتب li بشكل صريح. إذا توقعت "0 عناصر" وأعطاك محررك عنصرًا فارغًا واحدًا، فهذا اختلاف في تنفيذ المحرر.div>span*3>p، أين ينتهي p؟<div><span><p></p></span><span><p></p></span><span><p></p></span></div> — p هو ابن لكل span (لأن أقرب سياق هو span). *3 يكرر span فقط، و p يتبع كل span. هذا أحد أكثر الأنماط إرباكًا للمبتدئين: التمييز بين نطاق * (فقط العنصر السابق مباشرة) ونطاق > اللاحق (أقرب سياق).📖 ملخص
^تعني الصعود مستوى واحدًا، نقل السياق من ابن إلى أصله^^و^^^ينفذان صعودات متتالية؛ الصعود متجاوزًا الجذر يتوقف عند الجذر الافتراضي*Nيكرر العنصر السابق مباشرة N مرة، يعمل على أقرب عنصر حالي*Nو>يتعاونان:>يغير السياق،*Nيعمل على أقرب عنصر في السياق الجديد- الضرب المتداخل (مثل
*5tr يحتوي على*6td) يتطلب الأقواس()للتجميع (الدرس التالي) (tr>td*5)*6هو نمط الاختصار القياسي لـ "جدول ثنائي الأبعاد"
📝 تمارين
- أساسي (الصعوبة: ★): اكتب 3 اختصارات Emmet باستخدام
*تتوسع إلى: (أ) 5 li؛ (ب) 1 ul يحتوي على 3 li، كل li يحتوي على 1 a؛ (ج) 1 ul يحتوي على 1 li، الـ li يحتوي على 3 a. - متوسط (الصعوبة: ★★): حلل كيف يجب أن يتوسع
(nav>ul>li*3>a)+main+footer(ارسمه على الورق أولاً، ثم تحقق بالتوسيع). ثم أعد كتابته كنسخة مكافئة باستخدام^(بدون أقواس). - متقدم (الصعوبة: ★★★): اكتب اختصار Emmet واحدًا لجدول شطرنج 8×8 (الخلية الأولى هي
<th>عنوان، والباقي<td>). اشرح لماذا يتطلب هذا الهيكل الأقواس للتجميع. اكتب أيضًا "النسخة الخاطئة" بدون أقواس وقارن نتائج التوسيع الفعلية.