Dynamic component

 Dynamic component


 جدول المصطلحات والملاحظات

المصطلح (إنجليزي)

ملاحظات مهمة

Dynamic Components

مكونات تُنشأ أثناء وقت التشغيل (Runtime) وليس وقت البناء

ViewContainerRef

الحاوية التي سيُضاف إليها المكون الجديد

ComponentFactoryResolver

خدمة لإنشاء المكونات ديناميكياً (في Angular < 13)

ComponentRef

كائن يمثل المكون المنشأ ويسمح بالتحكم فيه

entryComponents

قائمة المكونات المسموح بإنشائها ديناميكياً

Runtime

الفترة التي يعمل فيها التطبيق على جهاز المستخدم

Compile Time

فترة إنشاء وتجميع التطبيق

Component Factory

كائن يعرف كيفية إنشاء نوع محدد من المكونات

DOM Manipulation

إضافة/إزالة عناصر من شجرة واجهة المستخدم

Memory Leak

مشكلة تحدث عندما لا نحرر الذاكرة المستخدمة


 المقدمة

ما هي المكونات الديناميكية؟

Dynamic Components في Angular هي مكونات لا تكون موجودة في القالب (Template) من البداية، بل يتم إنشاؤها برمجياً أثناء تشغيل التطبيق. تخيل أنك تبني تطبيقاً يمكن للمستخدم إضافة "قطع" (Widgets) إلى لوحة التحكم حسب رغبته - هنا تكمن قوة المكونات الديناميكية.

الفرق الجوهري

المكونات الثابتة

المكونات الديناميكية

موجودة في template من البداية

تُنشأ عند الحاجة فقط

تُخفي/تُظهر بـ *ngIf

تُنشأ/تُدمر برمجياً

تستهلك ذاكرة حتى وهي مخفية

تحرر الذاكرة عند التدمير

لماذا نستخدمها؟

  1. تحسين الأداء (Performance Optimization)

    • تحميل المكونات فقط عند الحاجة (Lazy Loading)

    • تقليل حجم التطبيق الأولي

  2. المرونة (Flexibility)

    • واجهات مستخدم قابلة للتخصيص

    • سلوك ديناميكي بناءً على البيانات

  3. فصل المسؤوليات (Separation of Concerns)

    • فصل منطق إنشاء المكونات عن منطق العرض

المكونات الأساسية المطلوبة

1. ViewContainerRef - الحاوية الذكية

typescript

// هذا هو المكان الذي سنضيف فيه المكونات الجديدة

@ViewChild('container', { read: ViewContainerRef }) 

container: ViewContainerRef;

الدور: مثل "صندوق الإضافة" الذي تستطيع وضع المكونات الجديدة داخله.

2. ComponentFactoryResolver - المنشئ

typescript

// في Angular < 13، نحتاج هذه الخدمة

constructor(private resolver: ComponentFactoryResolver) {}

الدور: يعطينا "قالب الإنشاء" للمكون الذي نريده.

3. ComponentRef - جواز السفر

typescript

// بعد الإنشاء، نحصل على هذا المرجع للتحكم بالمكون

const componentRef = container.createComponent(factory);

الدور: يمثل المكون المنشأ ويمكننا من:


  • تمرير البيانات إليه (componentRef.instance.property = value)

  • الاستماع لأحداثه (componentRef.instance.event.subscribe())

  • تدميره عند الانتهاء (componentRef.destroy())

 حالات عملية من الواقع

الحالة 1: نظام التنبيهات (Notification System)

typescript

// عندما يحدث خطأ

showError(message: string) {

  // 1. إنشاء المكون ديناميكياً

  const alertRef = this.createDynamicComponent(AlertComponent);

  

  // 2. تمرير البيانات

  alertRef.instance.message = message;

  alertRef.instance.type = 'error';

  

  // 3. إغلاق تلقائي بعد 5 ثوان

  setTimeout(() => alertRef.destroy(), 5000);

}

الحالة 2: مشغل الوسائط الديناميكي

typescript

// حسب نوع الملف

playMedia(fileType: string) {

  let playerComponent;

  

  if (fileType === 'video') {

    playerComponent = VideoPlayerComponent;

  } else if (fileType === 'audio') {

    playerComponent = AudioPlayerComponent;

  } else {

    playerComponent = ImageViewerComponent;

  }

  

  // إنشاء المشغل المناسب ديناميكياً

  this.createDynamicComponent(playerComponent);

}

الحالة 3: لوحة تحكم قابلة للتخصيص

المستخدم يختار الـ Widgets المفضلة، والتطبيق ينشئها ديناميكياً عند كل زيارة.

 المزايا الرئيسية

1. تحسين أداء التحميل (Load Performance)

  • مقارنة:

    • التطبيق التقليدي: يحمل كل المكونات مع التطبيق

    • التطبيق الديناميكي: يحمل المكونات عند الحاجة فقط

2. مرونة التصميم (Design Flexibility)

typescript

// يمكن تغيير المكون حسب دور المستخدم

if (user.isAdmin) {

  this.loadComponent(AdminPanelComponent);

} else {

  this.loadComponent(UserPanelComponent);

}

3. إدارة ذكية للذاكرة (Smart Memory Management)

  • المكون يُحمّل → يستخدم الذاكرة

  • المكون يُدمر → يحرر الذاكرة

  • لا تسرب ذاكرة (No Memory Leaks)

التحديات والحلول

التحدي 1: إدارة الذاكرة (Memory Management)

المشكلة: نسيان تدمير المكونات → تسرب ذاكرة

typescript

// ❌ خطأ شائع

createComponent() {

  const ref = this.container.createComponent(MyComponent);

  // نسيان تخزين المرجع للتدمير لاحقاً

}


// ✅ الحل الصحيح

private componentRefs: ComponentRef<any>[] = [];


createComponent() {

  const ref = this.container.createComponent(MyComponent);

  this.componentRefs.push(ref); // حفظ المرجع

}


destroyAll() {

  this.componentRefs.forEach(ref => ref.destroy());

  this.componentRefs = [];

}

التحدي 2: تمرير البيانات (Data Passing)

typescript

// ✅ الطريقة الصحيحة

const ref = this.container.createComponent(UserCardComponent);

ref.instance.user = currentUser; // Input

ref.instance.onDelete.subscribe(() => { // Output

  this.deleteUser();

});

التحدي 3: اكتشاف التغيرات (Change Detection)

typescript

// عند تعديل البيانات بعد الإنشاء

ref.instance.data = newData;

ref.changeDetectorRef.detectChanges(); // 🔄 إعادة الاكتشاف


 متى نختار المكونات الديناميكية؟

مقارنة سريعة

المعيار

*استخدم ngIf

استخدم Dynamic Components

التكرار

يظهر/يختفي كثيراً

يظهر نادراً

التعقيد

مكون بسيط

مكون معقد

الأداء

لا مشكلة في الأداء

يحتاج تحسين أداء

الذاكرة

حجم صغير

حجم كبير

قاعدة 80/20

  • 80% من الحالات: *ngIf أو *ngSwitch تكفي

  • 20% من الحالات: تحتاج Dynamic Components حقاً

 مثال حي من تطبيق بنكي

سيناريو: تطبيق بنك إلكتروني

typescript

// بناء الواجهة حسب نوع العملية

loadTransactionInterface(transactionType: string) {

  switch(transactionType) {

    case 'transfer':

      this.loadComponent(MoneyTransferComponent);

      break;

    case 'investment':

      this.loadComponent(InvestmentComponent);

      break;

    case 'loan':

      this.loadComponent(LoanApplicationComponent);

      break;

    default:

      this.loadComponent(DefaultTransactionComponent);

  }

}

النتيجة:

  • واجهة خفيفة وسريعة

  • كل مستخدم يحصل على الواجهة المناسبة لعمليته

  • ذاكرة مُدارة بكفاءة


 نصائح عملية للمطورين

للبدء (For Beginners)

  1. ابدأ بمشروع تجريبي صغير

  2. استخدم Dynamic Components لشيء بسيط أولاً (مثل Notification)

  3. تأكد من فهم إدارة الذاكرة قبل التوسع

للمتقدمين (For Advanced)

  1. فكر في Design Patterns مثل Factory Pattern

  2. استخدم Service لحفظ وإدارة المراجع

  3. اعمل على نظام Module Loading متقدم

للأداء (For Performance)

  1. استخدم Lazy Loading مع Dynamic Components

  2. ضع حداً أقصى للمكونات النشطة

  3. طبق Virtual Scrolling إذا كان هناك العديد من المكونات

 الخلاصة

المكونات الديناميكية (Dynamic Components) هي أداة متقدمة تمنحك تحكماً دقيقاً في:


  • أداء التطبيق - عن طريق التحميل عند الطلب

  • تجربة المستخدم - عن طريق واجهات مخصصة

  • إدارة الموارد - عن طريق تحرير الذاكرة غير المستخدمة


التحدي: تحتاج إلى فهم عميق لإدارة دورة حياة المكونات (Component Lifecycle).


المصادر والمراجع


Dynamic component  Dynamic component بواسطة Remocolla Academy في مارس 31, 2026 تقييم: 5

ليست هناك تعليقات:

يتم التشغيل بواسطة Blogger.