أفضل تجربة في إنشاء تطبيقات Angular نظيفة وسريعة

لكتابة هذه المقالة ، تم تشجيعهم من خلال البحث عن مطوري الواجهة الأمامية JavaScript في شركتهم في Stavropol. لأن لم يكن من الممكن العثور على مبرمج ذكي لفترة طويلة ، ثم قررنا إطلاق برنامج تدريب داخلي يحتوي على الكثير من المواد التدريبية على Angular & JS.

هذه ترجمة لمقال Vamsi Vempati حول تجربته مع تطبيق واسع النطاق لـ Trade Me كتب باللغة Angular.



حتى الآن ، عملت بالفعل لمدة عامين على تطبيق Angular واسع النطاق في Trade Me. خلال السنوات القليلة الماضية ، قام فريقنا بتحسين طلبنا من حيث معايير كتابة التعليمات البرمجية والأداء لجعله في أفضل حالة ممكنة.

توضح المقالة الطرق التي نستخدمها في مشروعنا. يرتبط النص في الغالب بـ Angular و TypeScript و RxJs و @ ngrx / store.

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

1) trackBy


عند استخدام ngFor لحلقة صفيف في القوالب ، ارجع إلى وظيفة trackBy ، والتي ستُرجع معرفًا فريدًا لكل عنصر.

لماذا؟


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

ملاحظة: يمكن العثور على وصف أكثر تفصيلاً في مقالة ناثانيل بزال. [المهندس]

إلى


 <li *ngFor="let item of items;">{{ item }}</li> 


بعد


 //   <li *ngFor="let item of items; trackBy: trackByFn">{{ item }}</li> //   trackByFn(index, item) { return item.id; // unique id corresponding to the item } 

2) كونت أو السماح؟


عند التصريح عن المتغيرات ، استخدم const إذا لم يتم إعادة تعيينها.

لماذا؟


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

إلى


 let car = 'ludicrous car'; let myCar = `My ${car}`; let yourCar = `Your ${car}`; if (iHaveMoreThanOneCar) { myCar = `${myCar}s`; } if (youHaveMoreThanOneCar) { yourCar = `${youCar}s`; } 

بعد


 //  car  ,      (const) const car = 'ludicrous car'; let myCar = `My ${car}`; let yourCar = `Your ${car}`; if (iHaveMoreThanOneCar) { myCar = `${myCar}s`; } if (youHaveMoreThanOneCar) { yourCar = `${youCar}s`; } 

3) تشبه الأنابيب المشغلين


استخدم عبارات تشبه توجيه RxJs عند العمل مع RxJs .
لا تتضمن عوامل التشغيل التي تشبه الأنابيب سوى الكود الذي يجب تنفيذه عند الاستيراد.

كما أنه يسهل العثور على عبارات غير مستخدمة في الملفات.

ملاحظة: الزاوي 5.5 وما فوق مطلوب.

إلى


 import 'rxjs/add/operator/map'; import 'rxjs/add/operator/take'; iAmAnObservable .map(value => value.item) .take(1); 

بعد


 import { map, take } from 'rxjs/operators'; iAmAnObservable .pipe( map(value => value.item), take(1) ); 

4) تسجيل الدخول القالب


تجنب الاشتراك في الكائنات المراقبة من المكونات - بدلاً من ذلك ، اشترك بها من قالب.

لماذا؟


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

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

إلى


 //  <p>{{ textToDisplay }}</p> //  iAmAnObservable .pipe( map(value => value.item), takeUntil(this._destroyed$) ) .subscribe(item => this.textToDisplay = item); 

بعد


 //  <p>{{ textToDisplay$ | async }}</p> //  this.textToDisplay$ = iAmAnObservable .pipe( map(value => value.item) ); 

5) اشتراكات واضحة


عند الاشتراك في الكائنات التي تتم مراقبتها ، تأكد دائمًا من إلغاء اشتراكك فيها بشكل مناسب باستخدام عوامل التشغيل مثل take ، takeUntil ، إلخ.

لماذا؟


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

علاوة على ذلك ، قم بإنشاء قاعدة lint للكشف عن الأشياء التي يمكن ملاحظتها والتي لا يوجد فيها إلغاء اشتراك.

إلى


 iAmAnObservable .pipe( map(value => value.item) ) .subscribe(item => this.textToDisplay = item); 


بعد


 private _destroyed$ = new Subject(); public ngOnInit (): void { iAmAnObservable .pipe( map(value => value.item) //     iAmAnObservable   ,     / takeUntil(this._destroyed$) ) .subscribe(item => this.textToDisplay = item); } public ngOnDestroy (): void { this._destroyed$.next(); this._destroyed$.complete(); } 

استخدام takeUntil للاستماع إلى التغييرات حتى يقوم كائن آخر takeUntil بإرجاع قيمة:

 iAmAnObservable .pipe( map(value => value.item), take(1), takeUntil(this._destroyed$) ) .subscribe(item => this.textToDisplay = item); 

لاحظ استخدام takeUntil مع take في المثال أعلاه. يؤدي ذلك إلى تجنب تسرب الذاكرة الناتج عن عدم تعيين قيمة للاشتراك قبل إزالة المكون.

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

6) كسل التحميل


حاول كلما أمكن ذلك تحميل الوحدات النمطية في تطبيق Angular فقط عندما تكون قيد الاستخدام.

لماذا؟


سيؤدي ذلك إلى تقليل حجم التطبيق الذي تم تنزيله وتقصير وقت التحميل.

إلى


 // app.routing.ts { path: 'not-lazy-loaded', component: NotLazyLoadedComponent } 

بعد


 // app.routing.ts { path: 'lazy-load', loadChildren: 'lazy-load.module#LazyLoadModule' } // lazy-load.module.ts import { NgModule } from '@angular/core'; import { CommonModule } from '@angular/common'; import { RouterModule } from '@angular/router'; import { LazyLoadComponent } from './lazy-load.component'; @NgModule({ imports: [ CommonModule, RouterModule.forChild([ { path: '', component: LazyLoadComponent } ]) ], declarations: [ LazyLoadComponent ] }) export class LazyModule {} 

تابع الترجمة في المقال التالي. إذا كان أي شخص لا يريد الانتظار ، فهناك رابط للمقال الأصلي.

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


All Articles