创建干净,快速的Angular应用程序方面的最佳经验

在撰写本文时,他们为在Stavropol公司中寻找JavaScript前端开发人员而感到鼓舞。 因为 长期以来,一直找不到智能的程序员,然后我们决定启动一个实习计划,其中包含有关Angular和JS的大量培训材料。

这是Vamsi Vempati文章的翻译,该文章讲述了他在Angular中使用Trade Me的大型应用程序的经验。



迄今为止,我已经在Trade Me上工作了几年,用于大型Angular应用程序。 在过去的几年中,我们的团队在代码编写标准和性能方面改进了我们的应用程序,以使其达到最佳状态。

本文概述了我们在项目中使用的方法。 文本主要与Angular,TypeScript,RxJs和@ ngrx / store相关联。

此外,还将考虑一些用于编写代码的通用准则,这些准则将有助于使应用程序更“干净”和易读。

1)追踪


当使用ngFor在模板中循环数组时,请参考trackBy函数,该函数将为每个元素返回唯一的标识符。

怎么了


当数组更改时,Angular会完全重绘DOM树。 但是,如果您使用trackBy函数,则Angular将了解哪个元素已更改,然后仅对该特定元素进行DOM更改。

注意:更详细的描述可以 Nathanel Bazal 的文章中找到。 [eng]


 <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还是让?


声明变量时,如果不重新分配变量,请使用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
类管道运算符仅包含导入时需要执行的代码。

这也使查找文件中未使用的语句变得更加容易。

注意:需要 Angular 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订阅源自动取消订阅,从而简化了代码并消除了手动订阅管理的需要。 还降低了意外取消订阅组件的风险,这将导致内存泄漏。 这可以通过使用lint规则检测未签名的观察对象来解决。

此外,它不允许组件保持静态,并且当订阅之外的数据发生更改时会增加错误。


 //  <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)清除订阅


订阅受监视的对象时,请始终确保使用诸如taketakeUntil等运算符对它们进行适当的退订。

怎么了


取消订阅观察到的对象所导致的错误将导致不希望的内存泄漏,因为观察到的流保持打开状态,即使在删除组件或用户移动到另一页时也是如此。

此外,创建一个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侦听更改,直到另一个观察到的对象返回值:

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

注意上面示例中的takeUntiltake的使用。 这样可以避免由于在删除组件之前没有为预订分配任何值而导致的内存泄漏。

如果没有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/zh-CN447042/


All Articles