Vue.js: الفتحات
آخر تحديث: 2026-10-20
تُعد «الفتحات» جزءًا من واجهة برمجة تطبيقات توزيع المحتوى في Vue — حيث يمكن للمكونات الأصلية إدراج أي محتوى في «الفتحات» الخاصة بالمكون الفرعي. وتجعل «الفتحات» المكونات مرنةً بقدر «القوالب»: فالمكونات الأصلية تتحكم في ما يتم عرضه، بينما تتحكم المكونات الفرعية في مكان عرضه.
يقدم Vue 3 ثلاثة أنواع من الفتحات: الفتحات الافتراضية، والفتحات المسماة، والفتحات ذات النطاق. سيساعدك هذا الدرس على إتقان استخدام هذه الأنواع الثلاثة وأفضل الممارسات المتعلقة بها.
1. ما ستتعلمه
- الاستخدام الأساسي للفتحة الافتراضية
<slot /> - الاختصارات الخاصة بالفتحات المسماة
<slot name="header" />وv-slot:header - فتحات النطاق: تقوم المكونات الفرعية بتمرير البيانات إلى فتحات المكون الرئيسي
<template v-slot>قواعد الصياغة (Vue 2.6+)- أسماء الخانات الديناميكية وقواعد كتابة الاختصارات
- محتوى الفتحة الافتراضي (المحتوى البديل)
$slots/useSlotsوصلة
2. التحدي المتمثل في عدم القدرة على تخصيص محتوى مكون البطاقة
(1) المشكلة: 5 أنماط للبطاقات، تتطلب كتابة 5 مكونات
احتاج مسؤول التجارة الإلكترونية لدى أليس إلى 5 أنواع من البطاقات:
<!-- ❌ 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) الإيرادات
بعد استخدام ماكينات القمار:
- عدد المكونات: 5 → 1 (-80%)
- نوع البطاقة الجديد: سطر واحد من كود «موديلو»
- تكاليف الصيانة: بمجرد تغيير نمط واحد، يتم تحديث أكثر من 5 بطاقات في آن واحد
- إمكانية إعادة الاستخدام: يمكن استخدام BaseCard في جميع الحالات المتعلقة بالبطاقات
3. الفتحة الافتراضية
(1) الاستخدام الأساسي
نتائج العرض:
<div class="card">
<h3>Hello</h3>
<p>This is the card content</p>
</div>
(2) المحتوى الافتراضي (الاحتياطي)
<!-- 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
▶ جرّب الكودالإخراج:
الاستخدام 1 → بطاقة بجسم فقط
الاستخدام 2 → رأس وجسم
الاستخدام 3 → رأس وجسم وتذييل بزر
الاستخدام 5 → فتحة النطاق تمرّر user
4. الفتحات المسماة
(1) تعريف الفتحات المسماة
(2) استخدام المكونات الأصلية (3 صيغ)
(3) أسماء الخانات الديناميكية
(4) التحقق من وجود فتحة
5. فتحات النطاق
(1) نقطة أساسية: تقوم المكونات الفرعية بتمرير البيانات إلى فتحات المكون الرئيسي
نتائج العرض:
<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) مثال كامل: قائمة قابلة للتخصيص
▶ جرّب الكود▶ مثال: تطبيق كامل على فتحات النطاق
▶ جرّب الكودالإخراج:
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 (واجهة برمجة التطبيقات للتكوين)
<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
▶ جرّب الكودالإخراج:
slots.header موجود → يظهر Has header
Object.keys(slots) يحصر أسماء الفتحات
v-bind=attrs يمرّر الخصائص إلى input
7. تمرين شامل: مكوّن BaseCard بفتحات افتراضية ومسماة
▶ مثال: BaseCard.vue (الافتراضي + الفتحات المسماة)
▶ جرّب الكودالإخراج:
بدون فتحات → يظهر النص الافتراضي No content
مع الفتحة header → شريط رأس أعلى البطاقة
مع الفتحة footer → شريط تذييل أسفل البطاقة
❓ أسئلة شائعة
v-slot و#؟#header is a shorthand for v-slot:header. نوصي باستخدام الاختصار (لأنه أكثر إيجازًا).<slot /> هي القيمة الافتراضية. إذا كان لا بد من تسميتها، فاستخدم <slot name="default" />؛ ويمكن للمكون الأصلي استخدام <template #default> أو ببساطة تمرير المحتوى مباشرةً.<slot>.$slots (قالب) أو useSlots() (JS). يقوم المكون التابع بإتاحة الفتحة باستخدام <slot>، بينما يقوم المكون الرئيسي بملئها باستخدام <template #name>.<slot name="header"><h3>Default Header</h3></slot>. يتم عرض هذا المحتوى عندما لا يقوم المكون الأصلي بتمرير رأس.📖 ملخص
- «السلوتات» هي واجهة برمجة تطبيقات توزيع المحتوى في Vue: حيث تتحكم المكونات الأم في المحتوى، بينما تتحكم المكونات الفرعية في موضع العرض
- 3 أنواع من الفتحات: الفتحة الافتراضية (
<slot />)، والفتحة المسماة (name="x")، والفتحة ذات النطاق المحدد (:x="x") - يقوم المكون الأصلي بتمرير فتحة مسماة باستخدام
<template #name>أو الاختصار#name - تتيح فتحات النطاق للمكونات الفرعية تمرير البيانات إلى المكونات الأصلية (خصائص الفتحة)
<slot>المحتوى الافتراضي (الاحتياطي) الذي يتم عرضه عندما لا يمرر المكون الأصلي أي محتوى$slots/useSlots()التحقق من وجود الفتحة- التعامل مع «السلوتات» و«العناصر المساعدة»: تقوم «العناصر المساعدة» بتمرير الإعدادات، بينما تقوم «السلوتات» بتمرير المحتوى
📝 تمارين
-
أسئلة أساسية (مستوى الصعوبة: ⭐)
تنفيذ مكون «زر» بسيط:
- BaseButton.vue: الفتحة الافتراضية + 3 أشكال (أساسي/نجاح/خطر)
- props:
variant(سلسلة) - المكون الأصلي: اختبار 3 متغيرات + محتوى مخصص للفتحة
-
مسائل متقدمة (مستوى الصعوبة: ⭐⭐)
تنفيذ مكون BaseLayout:
- المكونات الفرعية: 3 خانات مسماة (رأس الصفحة / الافتراضي / تذييل الصفحة)
- المكون الأصلي: استخدم «BaseLayout» لتنفيذ صفحة لوحة التحكم
- استخدم
$slotsللتحقق من وجود الفتحة - إضافة محتوى افتراضي (احتياطي)
-
مسألة التحدي (مستوى الصعوبة: ⭐⭐⭐)
تنفيذ نظام مكونات DataTable كامل:
- DataTable.vue: يستقبل الأعمدة والبيانات، ويقوم بعرض الجدول
- خانة النطاق:
#cell-{key}تتيح للمكونات الأصلية تخصيص الخلايا - الخانة الافتراضية: تعرض القيمة الأصلية عندما لا يوفر المكون الأصلي قيمةً ما
- مثال على المكون الأصلي: جدول المستخدمين + جدول الطلبات — طريقتان مختلفتان لعرض الأعمدة
- الأداء: يقوم v-memo بتخزين الصفوف مؤقتًا (يتخطى إعادة الرسم عندما تظل البيانات دون تغيير)
- التعيين القوي للأنواع في TypeScript