مكونات الزاوي مع مضمنة المحتوى

عندما تنشئ مكونات جديدة عند التطوير على Angular ، فإنك تسعى جاهدين إلى إنشائها بطريقة يمكن إعادة استخدامها عدة مرات. كما هو الحال في تطوير البرمجيات ، يسعى المبرمج إلى جعل كوده قابلاً لإعادة الاستخدام قدر الإمكان. في الوقت نفسه ، أريد أن أمتلك مكونات مرنة ، لكن ليست معقدة للغاية.



وكقاعدة عامة ، يجب أن تكون المكونات غبية قدر الإمكان حتى يسهل صيانتها واختبارها. ولكن في الوقت نفسه ، فهي قابلة للتخصيص ومرنة بحيث يمكنك إعادة استخدامها عدة مرات ، وليس التعامل مع مكونات الاستنساخ التي تشبه بصريا ووظيفيا ، ولكن لا تزال تختلف في شيء ما. أو لا تضيف مجموعة من المعلمات إلى المكونات ، بناءً على تمكين أو تعطيل أي سلوك للمكون ، ولكن في الواقع سيتم استخدامه في 1 من أصل 100 حالة.

لإنشاء غواصة ، والتي يجب أن تغرق في قاع البحر الأزرق دون المخاطرة بحياة الطاقم ، ثم تعديله قبل أن يطير في السماء الزرقاء ليست مهمة سهلة.

المكون الزاوي هو أصغر وحدة من واجهة المستخدم التي يجب أن تؤدي مهمة واحدة بسيطة ولا شيء أكثر من ذلك. إنشاء مكونات لجميع المناسبات هو ممارسة سيئة. لذلك ، عليك أن تجد حلا وسطا بين المرونة والبساطة.

لنفترض أنك تريد إنشاء مكون يتكون من نوع من المجمع ، يوجد بداخله رأس ونوع من التبديل ، وبعض المحتوى الموجود تحتها. شيء مثل هذا:



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

ولكن ماذا لو تم جعل هذا المكون أكثر مرونة ، على سبيل المثال ، بحيث يتغير المحتوى اعتمادًا على معلمات مكون عنصر واجهة المستخدم؟

يمكنك حل التمثيل الخارجي للمحتوى استنادًا إلى معلمة عنصر واجهة المستخدم ، على سبيل المثال ، باستخدام التوجيه الهيكلي ngIf . يمكنك التبديل بين وجهات النظر المختلفة. وإذا كان هناك الكثير من عمليات التقديم ، يمكنك استخدام التوجيه الهيكلي ngSwitch آخر.

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

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

في هذه الحالة ، يمكن تمثيل مكون عنصر واجهة المستخدم كما يلي:

// widget.component.ts … private widgetContentTemplate: TemplateRef<any>; //      @ContentChild(WidgetContentTemplateDirective, { read: TemplateRef }) set WidgetContentTemplate(value: TemplateRef<any>) { this.widgetContentTemplate = value; } get WidgetContentTemplate(): TemplateRef<any> { return this.widgetContentTemplate; } … 

 <!-- widget.component.html --><div class="widget__content"> <!--      ,      context.   ,     --> <ng-container *ngTemplateOutlet="WidgetContentTemplate || DefaultWidgetContentTemplate; context: { post: SelectedPost }"> </ng-container> </div> <ng-template #DefaultWidgetContentTemplate> <div>[    ]</div> </ng-template> 

يقبل التوجيه ngTemplateOutlet كائن TemplateRef الذي يتم قراءته في المكون باستخدامContentChild. للقيام بذلك ، تحتاج إلى إنشاء توجيه بسيط. هنا كودها:

 // widget-content-template.directive.ts import { Directive, TemplateRef } from '@angular/core'; @Directive({ selector: '[appWidgetContentTemplate]' }) export class WidgetContentTemplateDirective { get Template(): TemplateRef<any> { return this.template; } constructor(private readonly template: TemplateRef<any>) {} } 

يمكن تمرير المعلمات من مفتاح عنصر واجهة المستخدم إلى المحتوى باستخدام كائن السياق. لكي تتم قراءة المعلمات من السياق بشكل صحيح بواسطة المكون ، من الضروري في المكون الأصل ، وفي حالتنا هو AppComponent ، لا تنس أن تصفها كما يلي:

 <!-- app.component.html --> <app-widget-component Title="  (  )"> <!-- let-post="post" ,         --> <ng-template appWidgetContentTemplate let-post="post"> <app-post-view [Post]="post"></app-post-view> </ng-template> </app-widget-component> <br> <br> <app-widget-component Title="  (  )"> <!--  let-post="post"     ,  ShowPostInfo  AppComponent --> <ng-template appWidgetContentTemplate let-post="post"> <app-post-view [Post]="post" [ShowPostInfo]="ShowPostInfo"></app-post-view> </ng-template> </app-widget-component> 

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



يمكن رؤية النسخة الكاملة من الكود هنا .

Source: https://habr.com/ru/post/ar478886/


All Articles