مقاربات لإدارة الوحدات النمطية في الزاوي (وليس فقط)

إن فهم تنظيم الكيانات التي تعمل معها ليس شيئًا يأتي فورًا من مطور يكتب مشاريعه الأولى في Angular.


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


لحسن الحظ ، تزود Angular المطورين بالقدرة على إنشاء وحدات خاصة بهم ، وتدعو لهم أيضًا الوحدات النمطية للميزات.




وحدات ميزة المجال


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


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


صورة

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


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


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


تحميل كسول


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


الخدمات والحاقن


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


عن طريق الحقن وحدات تحميل كسول


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


اتضح أنه يمكن الإعلان عن الخدمات في أي وحدة ولا تقلق؟ ليس حقا مثل ذلك.


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


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


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


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


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


بالرجوع إلى الوحدات النمطية لميزات المجال ، يمثل السلوك الموضح طريقة واحدة للحد من عمر الموفرين المعلنين فيها.


الوحدة الأساسية


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


بدءًا من الإصدار 6 ، في الزاوية ، كانت هناك فرصة لإعلان الخدمات العالمية دون استيرادها في أي مكان. كل ما عليك فعله هو إضافة خيار provideIn إلى Injectable وتحديد القيمة 'root' فيه. تصبح الخدمات المعلنة بهذه الطريقة متاحة للتطبيق بالكامل ، وبالتالي ليست هناك حاجة إلى الإعلان عنها في الوحدة النمطية.


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


اختبار سينغلتون


ولكن ماذا لو أراد شخص ما في المشروع استيراد الوحدة الأساسية في مكان آخر؟ هل من الممكن أن تحمي نفسك من هذا؟ يمكنك ذلك.


أضف مُنشئًا إلى الوحدة النمطية Core يطلب منك حقن الوحدة النمطية في الوحدة النمطية (هذا صحيح ، أنت نفسك) ، وقم بتمييز هذا الإعلان باستخدام أدوات الديكور الاختيارية و SkipSelf. إذا وضع الحاقن تبعية في متغير ، فإن شخصًا ما يحاول إعادة إعلان الوحدة الأساسية.


باستخدام النهج في BrowserModule

باستخدام النهج الموضح في BrowserModule .


يمكن استخدام هذا النهج مع كل من الوحدات والخدمات.


إعلان الخدمة في المكون


لقد فكرنا بالفعل في طريقة للحد من نطاق مقدمي الخدمة الذين يستخدمون التحميل البطيء ، لكن هذا آخر.


كل مثيل مكون له حاقن خاص به ، ولتكوينه ، تمامًا مثل أداة تزيين NgModule ، يمتلك مصمم المكون خاصية الموفر. وأيضا - خاصية إضافية من viewProviders. كلاهما يعمل على تكوين مكونات الحاقن ، ومع ذلك ، فإن مقدمي الخدمات المعلنين في كل من الطرق لديهم نطاقات مختلفة.


لفهم الفرق ، تحتاج إلى خلفية قصيرة.


مكون يتكون من العرض والمحتوى.


أنا تطور المكونات

عرض المكونات


أنا مكونات المحتوى

مكونات المحتوى


كل ما هو موجود في ملف html الخاص بالمكون هو وجهة نظره ، في حين أن ما يتم تمريره بين علامات مكون الفتح والإغلاق هو محتواه.


النتيجة التي تم الحصول عليها:


النتيجة

النتيجة


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


على الرغم من أنه من أفضل الممارسات التصريح بالخدمات في حاقن الجذر ، هناك سيناريوهات عند استخدام مكون الحاقن في متناول اليد:


الأول هو عندما يجب أن يكون لكل مثيل مكون جديد مثيل خدمة خاص به. على سبيل المثال ، خدمة تخزن بيانات خاصة بكل مثيل جديد لمكون.


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


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


مكونات قابلة لإعادة الاستخدام


ماذا تفعل مع المكونات التي نريد إعادة استخدامها؟ لا يوجد أيضًا إجابة محددة على هذا السؤال ، ولكن هناك أساليب مثبتة.


وحدة مشتركة


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


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


تسمى هذه الوحدة عادة SharedModule.


من المهم ملاحظة أن SharedModule يجب ألا تعلن عن الخدمات. أو أعلن استخدام نهج forRoot. سنتحدث عنه بعد قليل.


على الرغم من أن نهج SharedModules يعمل ، فهناك بضع نقاط لذلك:


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

النهج الذي يخلو من هذه العيوب هو وينطوي على إنشاء وحدة نمطية لكل مكون.


وحدة لكل مكون أو عملية احتيال (وحدة الزاوي مكون واحد)


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



صورة

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


في اللغة الإنجليزية ، تسمى هذه الوحدة النمطية لكل مكون أو SCAM - وحدة الزاوي المكون المفرد. على الرغم من أن الاسم يحتوي على مكون الكلمة ، إلا أن هذا النهج ينطبق أيضًا على المواسير والتوجيهات (الرسائل الاقتحامية (SPAM) ، SDAM).


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


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


ModuleWithProviders واجهة


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


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


استراتيجيات forRoot () ، forChild ()


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


صورة


يمكن أن تكون الطرق التي تُرجع ModuleWithProviders أي رقم ، ويمكن تسميتها كما تريد. forRoot هي اتفاقية أكثر ملاءمة من المتطلبات.


على سبيل المثال ، يحتوي RouterModule على طريقة ثابتة forChild ، والتي يتم استخدامها لتكوين التوجيه في الوحدات النمطية المحملة بالكسل.


الاستنتاج:


  1. افصل بين واجهة المستخدم والمهام الأساسية ، وقم بإنشاء الوحدة الخاصة بك لكل جزء محدد: بالإضافة إلى طريقة أكثر ملاءمة لفهم بنية رمز المشروع ، احصل على فرصة تحميل أجزاء من الواجهة بتكاسل
  2. استخدم حاقن الوحدات والمكونات المحملة بالكسل إذا كانت بنية التطبيق تتطلب ذلك
  3. نشر إعلانات الخدمة العالمية في وحدة نمطية منفصلة ، وحدة Core ، واستيرادها فقط في وحدة التطبيق. هذا سوف يساعد في تنظيف وحدة التطبيق.
  4. أفضل من ذلك ، استخدم خيار provideIn مع القيمة الجذرية لديكور Injectable.
  5. استخدم الاختراق مع أدوات الديكور الاختيارية و SkipSelf لمنع إعادة استيراد الوحدات والخدمات
  6. تخزين المكونات القابلة لإعادة الاستخدام والتوجيهات والأنابيب في الوحدة المشتركة
  7. ومع ذلك ، فإن أفضل طريقة ، والتي تتطلع أيضًا إلى المستقبل ، وتسهل الاختبار هي إنشاء وحدة نمطية لكل مكون (التوجيهات والأنابيب ، أيضًا)
  8. استخدم واجهة ModuleWithProviders إذا كنت تريد تجنب تعارضات الموفر. تتمثل الطريقة الشائعة في تنفيذ طريقة forRoot لإضافة موفرين إلى وحدة الجذر

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


All Articles