Vue.js: الفتحات

آخر تحديث: 2026-10-20

تُعد «الفتحات» جزءًا من واجهة برمجة تطبيقات توزيع المحتوى في Vue — حيث يمكن للمكونات الأصلية إدراج أي محتوى في «الفتحات» الخاصة بالمكون الفرعي. وتجعل «الفتحات» المكونات مرنةً بقدر «القوالب»: فالمكونات الأصلية تتحكم في ما يتم عرضه، بينما تتحكم المكونات الفرعية في مكان عرضه.

يقدم Vue 3 ثلاثة أنواع من الفتحات: الفتحات الافتراضية، والفتحات المسماة، والفتحات ذات النطاق. سيساعدك هذا الدرس على إتقان استخدام هذه الأنواع الثلاثة وأفضل الممارسات المتعلقة بها.

القوالب والمساعدات ذات صلة:useSlots()

1. ما ستتعلمه


2. التحدي المتمثل في عدم القدرة على تخصيص محتوى مكون البطاقة

(1) المشكلة: 5 أنماط للبطاقات، تتطلب كتابة 5 مكونات

احتاج مسؤول التجارة الإلكترونية لدى أليس إلى 5 أنواع من البطاقات:

VUE
<!-- ❌ The "Broken" Version:5 component -->
<!-- ProductCard.vue -->
<div class="card">{{ product.name }}</div>

<!-- UserCard.vue -->
<div class="card">{{ user.name }}</div>

<!-- OrderCard.vue -->
<div class="card">Order #{{ order.id }}</div>

<!-- 5 component,90% The code is the same,The only difference is the content -->

مدير المنتج تشارلي:

«أليس، أحتاج إلى 5 أنواع إضافية من البطاقات الأسبوع المقبل. لا يمكننا الاستمرار في إضافة مكونات جديدة. نحن بحاجة إلى بطاقة مرنة تقبل أي محتوى.»

(2) حل «الفتحات» في Vue: بطاقة أساسية واحدة (BaseCard)، مع محتوى مقدم من المكون الأصلي

1 BaseCard.vue → مجموعة لا حصر لها من البطاقات. في كل مرة تضيف فيها بطاقة جديدة، ما عليك سوى كتابة المحتوى — دون الحاجة إلى تعديل المكون.

(3) الإيرادات

بعد استخدام ماكينات القمار:


3. الفتحة الافتراضية

(1) الاستخدام الأساسي

نتائج العرض:

HTML
<div class="card">
  <h3>Hello</h3>
  <p>This is the card content</p>
</div>

(2) المحتوى الافتراضي (الاحتياطي)

VUE
<!-- The parent component does not pass content -->
<BaseCard />

<!-- Rendering:<p>No content provided</p> -->

<!-- Passing Content from the Parent Component -->
<BaseCard>
  <p>Custom content</p>
</BaseCard>

<!-- Rendering:<p>Custom content</p>(Override Default)-->

(3) 5 حالات استخدام رئيسية

السيناريو الاستخدام
محتوى البطاقة <slot />
نص الزر <slot />
عنصر القائمة <slot :item="item" />
حقل النموذج <slot />
نص مربع منبثق <slot />

▶ مثال: 5 طرق لاستخدام بطاقة BaseCard

▶ جرّب الكود

الإخراج:

TEXT
الاستخدام 1 → بطاقة بجسم فقط
الاستخدام 2 → رأس وجسم
الاستخدام 3 → رأس وجسم وتذييل بزر
الاستخدام 5 → فتحة النطاق تمرّر user

4. الفتحات المسماة

(1) تعريف الفتحات المسماة

(2) استخدام المكونات الأصلية (3 صيغ)

(3) أسماء الخانات الديناميكية

(4) التحقق من وجود فتحة


5. فتحات النطاق

(1) نقطة أساسية: تقوم المكونات الفرعية بتمرير البيانات إلى فتحات المكون الرئيسي

نتائج العرض:

HTML
<ul>
  <li><p>1. Alice (alice@example.com)</p></li>
  <li><p>2. Bob (bob@example.com)</p></li>
  <li><p>3. Charlie (charlie@example.com)</p></li>
</ul>

(2) 5 أنماط لفتحات المنظار

النمط تنفيذ المكون الأصلي الغرض
يقبل جميع العناصر <template #default="slotProps"> يقبل الكائن بأكمله
التفكيك <template #default="{ user }"> استخدم الحقول التي تحتاجها فقط
إعادة التسمية <template #default="{ user: u }"> تجنب تعارض المتغيرات
القيمة الافتراضية <template #default="{ user = defaultUser }"> إدخال قيمة افتراضية أثناء عملية التفكيك
لا يوجد قالب {{ slotProps.user.name }} سيناريو بسيط (الفتحة الافتراضية)

(3) مثال كامل: قائمة قابلة للتخصيص

▶ جرّب الكود

▶ مثال: تطبيق كامل على فتحات النطاق

▶ جرّب الكود

الإخراج:

TEXT
DataTable يعرض الأعمدة والصفوف افتراضيًا
الفتحة cell-status تعرض شارة بلون الحالة
الفتحة cell-actions تعرض زر Edit لكل صف

(1) 📊 4. مرجع سريع لـ 5 أخطاء شائعة

الخطأ الأعراض الحل
اسم الخانة مكتوب بشكل خاطئ المحتوى غير معروض تحقق من تطابق <slot name="..."> و#name
وجود عناصر جذرية متعددة في المكون الأصلي تحذير المكون الأصلي محاط بtag <template #name>
v-slot (الصيغة القديمة) متوافق مع Vue 2 استخدم v-slot:header أو #header بدلاً من ذلك
لم يتم تمرير الخانة الافتراضية لم يتم عرض المكون الأصلي تحقق من محتوى <Component /> في المكون الأصلي
لا يتم تفكيك فتحات النطاق القوالب مطولة التفكيك باستخدام { user, index }

(2) 📊 5. 5 مقارنات الأداء

بناء الجملة الترجمة الأداء التوصيات
<slot /> ثابت ⭐⭐⭐⭐⭐ افتراضي
<slot name="x" /> ثابت ⭐⭐⭐⭐⭐ مسمى
<slot :x="x" /> ثابت ⭐⭐⭐⭐ النطاق
v-if="$slots.x" الstatus ⭐⭐⭐⭐ تم الكشف عنها
useSlots() وقت التشغيل ⭐⭐⭐ يُستخدم في JS

6. $slots و useSlots

(1) $slots الوصول إلى الفتحات

(2) useSlots (واجهة برمجة التطبيقات للتكوين)

VUE
<script setup>
import { useSlots } from 'vue'

const slots = useSlots()

// Check if the slot exists
if (slots.header) {
  console.log('Header slot exists')
}

// Dynamic Rendering
if (slots.default) {
  console.log('Default slot exists')
}
</script>

(3) $slots مقابل useSlots

البعد $slots useSlots()
نوع واجهة برمجة التطبيقات (API) تُستخدم مباشرةً في القوالب تُستخدم في JavaScript (واجهة برمجة التطبيقات للتركيب)
العودة كائن الفتحة كائن الفتحة (تنسيق المراجع)
المشهد داخل القالب داخل <script setup>

▶ مثال: 5 استخدامات رئيسية لـ $slots

▶ جرّب الكود

الإخراج:

TEXT
slots.header موجود → يظهر Has header
Object.keys(slots) يحصر أسماء الفتحات
v-bind=attrs يمرّر الخصائص إلى input


7. تمرين شامل: مكوّن BaseCard بفتحات افتراضية ومسماة

▶ مثال: BaseCard.vue (الافتراضي + الفتحات المسماة)

▶ جرّب الكود

الإخراج:

TEXT
بدون فتحات → يظهر النص الافتراضي No content
مع الفتحة header → شريط رأس أعلى البطاقة
مع الفتحة footer → شريط تذييل أسفل البطاقة


القوالب والمساعدات ذات صلة:useSlots()

❓ أسئلة شائعة

س ما الفرق بين «السلوتات» و«البروب»؟
ج تقوم «البروب» بتمرير البيانات (أي قيمة في JavaScript)، بينما تقوم «السلوتات» بتمرير المحتوى (أجزاء من HTML أو المكونات). وتُعد «البروب» مناسبة لخيارات التهيئة، في حين تُعد «السلوتات» مناسبة لتخصيص المحتوى.
س متى ينبغي استخدام فتحات النطاق؟
ج عندما يحتاج مكون أب إلى تخصيص طريقة عرضه استنادًا إلى البيانات الواردة من مكون تابع. على سبيل المثال: عرض أعمدة الجدول، أو عرض عناصر القائمة، أو تخطيط محتوى البطاقات.
س ما الفرق بين الاختصار v-slot و#؟
ج إنهما متطابقان تمامًا؛ #header is a shorthand for v-slot:header. نوصي باستخدام الاختصار (لأنه أكثر إيجازًا).
س هل يمكن تسمية الخانة الافتراضية؟
ج لا يلزم تسمية الخانة الافتراضية؛ <slot /> هي القيمة الافتراضية. إذا كان لا بد من تسميتها، فاستخدم <slot name="default" />؛ ويمكن للمكون الأصلي استخدام <template #default> أو ببساطة تمرير المحتوى مباشرةً.
س هل يمكن تمرير الخانات كمعلمات؟
ج لا يمكنك تمرير خانة مباشرةً كمعلمة. ومع ذلك، يمكنك تمرير VNode أو دالة عرض كمعلمة (استخدام متقدم). في معظم الحالات، ما عليك سوى استخدام <slot>.
س كيف يمكنني تحديد فتحة مكون تابع في مكون رئيسي؟
ج استخدم $slots (قالب) أو useSlots() (JS). يقوم المكون التابع بإتاحة الفتحة باستخدام <slot>، بينما يقوم المكون الرئيسي بملئها باستخدام <template #name>.
س هل يمكن أن تحتوي الخانات المسماة على محتوى افتراضي؟
ج نعم. <slot name="header"><h3>Default Header</h3></slot>. يتم عرض هذا المحتوى عندما لا يقوم المكون الأصلي بتمرير رأس.

📖 ملخص


📝 تمارين

  1. أسئلة أساسية (مستوى الصعوبة: ⭐)

    تنفيذ مكون «زر» بسيط:

    • BaseButton.vue: الفتحة الافتراضية + 3 أشكال (أساسي/نجاح/خطر)
    • props: variant (سلسلة)
    • المكون الأصلي: اختبار 3 متغيرات + محتوى مخصص للفتحة
  2. مسائل متقدمة (مستوى الصعوبة: ⭐⭐)

    تنفيذ مكون BaseLayout:

    • المكونات الفرعية: 3 خانات مسماة (رأس الصفحة / الافتراضي / تذييل الصفحة)
    • المكون الأصلي: استخدم «BaseLayout» لتنفيذ صفحة لوحة التحكم
    • استخدم $slots للتحقق من وجود الفتحة
    • إضافة محتوى افتراضي (احتياطي)
  3. مسألة التحدي (مستوى الصعوبة: ⭐⭐⭐)

    تنفيذ نظام مكونات DataTable كامل:

    1. DataTable.vue: يستقبل الأعمدة والبيانات، ويقوم بعرض الجدول
    2. خانة النطاق: #cell-{key} تتيح للمكونات الأصلية تخصيص الخلايا
    3. الخانة الافتراضية: تعرض القيمة الأصلية عندما لا يوفر المكون الأصلي قيمةً ما
    4. مثال على المكون الأصلي: جدول المستخدمين + جدول الطلبات — طريقتان مختلفتان لعرض الأعمدة
    5. الأداء: يقوم v-memo بتخزين الصفوف مؤقتًا (يتخطى إعادة الرسم عندما تظل البيانات دون تغيير)
    6. التعيين القوي للأنواع في TypeScript
Web-Tutorial.com

فريق Web-Tutorial التقني

منصة دروس برمجية يديرها عدة مطورين. كل درس يتم كتابته ومراجعته بواسطة مطورين متخصصين في المجال. نعمل على ضمان دقة وموثوقية المحتوى — إذا لاحظت أي مشكلة، فيرجى إخبارنا.

100%