Beste Erfahrung bei der Erstellung sauberer und schneller Angular-Anwendungen

Um diesen Artikel zu schreiben, wurden sie durch die Suche nach JavaScript-Front-End-Entwicklern in ihrem Unternehmen in Stawropol ermutigt. Weil Lange Zeit war es nicht möglich, einen intelligenten Programmierer zu finden, und dann beschlossen wir, ein Praktikumsprogramm mit viel Schulungsmaterial zu Angular & JS zu starten.

Dies ist eine Übersetzung eines Artikels von Vamsi Vempati über seine Erfahrungen mit einer groß angelegten Anwendung für Trade Me in Angular.



Bisher habe ich bereits einige Jahre bei Trade Me an einer groß angelegten Angular-Anwendung gearbeitet. In den letzten Jahren hat unser Team unsere Anwendung hinsichtlich der Standards und der Leistung für das Schreiben von Code verfeinert, um sie auf den bestmöglichen Stand zu bringen.

Der Artikel beschreibt die Methoden, die wir in unserem Projekt verwenden. Der Text ist hauptsächlich mit Angular, TypeScript, RxJs und @ ngrx / store verknüpft.

Darüber hinaus werden einige allgemeine Richtlinien zum Schreiben von Code berücksichtigt, die dazu beitragen, die Anwendung „sauberer“ und lesbarer zu machen.

1) trackBy


Wenn Sie ngFor zum Schleifen eines Arrays in Vorlagen verwenden, trackBy Funktion trackBy , die für jedes Element eine eindeutige Kennung trackBy .

Warum?


Wenn sich das Array ändert, zeichnet Angular den DOM-Baum vollständig neu. Wenn Sie jedoch die Funktion trackBy verwenden, versteht Angular, welches Element sich geändert hat, und nimmt dann nur für dieses bestimmte Element Änderungen am DOM vor.

Hinweis: Eine ausführlichere Beschreibung finden Sie im Artikel von Nathanel Bazal. [deu]

Zu


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


Nachher


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

2) const oder let?


Verwenden Sie beim Deklarieren von Variablen const wenn diese nicht neu zugewiesen werden.

Warum?


Die Verwendung von let und const macht den Grund für die Deklaration von Variablen gegebenenfalls verständlicher. Es kann auch helfen, Probleme zu identifizieren, wenn ein Wert aufgrund eines Fehlers bei der Kompilierung zufällig einer Konstanten zugewiesen wird. Es verbessert auch die Lesbarkeit des Codes.

Zu


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

Nachher


 //  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) Rohrartige Bediener


Verwenden Sie Pipe-ähnliche Anweisungen, wenn Sie mit RxJs .
Pipe-ähnliche Operatoren enthalten nur den Code, der beim Import ausgeführt werden muss.

Es erleichtert auch das Auffinden nicht verwendeter Anweisungen in Dateien.

Hinweis: Winkel 5,5 und höher ist erforderlich.

Zu


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

Nachher


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

4) Melden Sie sich in der Vorlage an


Vermeiden Sie das Abonnieren von überwachten Objekten aus Komponenten. Abonnieren Sie sie stattdessen aus einer Vorlage.

Warum?


async Feeds werden automatisch abgemeldet, wodurch der Code vereinfacht wird und keine manuelle Abonnementverwaltung erforderlich ist. Das Risiko eines versehentlichen Abbestellens einer Komponente wird ebenfalls verringert, was zu einem Speicherverlust führt. Dies kann behoben werden, indem die Flusenregel verwendet wird, um nicht signierte beobachtete Objekte zu erkennen.

Darüber hinaus können Komponenten nicht statisch bleiben und Fehler hinzufügen, wenn sich Daten außerhalb des Abonnements ändern.

Zu


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

Nachher


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

5) Abonnements löschen


takeUntil Sie beim Abonnieren von überwachten Objekten immer sicher, dass Sie sie mit Operatoren wie take , takeUntil usw. takeUntil .

Warum?


Fehler beim Abbestellen von beobachteten Objekten führen zu einem unerwünschten Speicherverlust, da der beobachtete Stream offen bleibt, wahrscheinlich auch nach dem Entfernen der Komponente oder wenn der Benutzer zu einer anderen Seite wechselt.

Erstellen Sie außerdem eine lint , um beobachtbare Objekte zu erkennen, von denen keine Abmeldung vorliegt.

Zu


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


Nachher


 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(); } 

Verwenden Sie takeUntil , um auf Änderungen zu takeUntil , bis ein anderes beobachtetes Objekt einen Wert zurückgibt:

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

Beachten Sie die Verwendung von takeUntil zusammen mit take im obigen Beispiel. Dadurch werden Speicherverluste vermieden, die dadurch verursacht werden, dass dem Abonnement vor dem Entfernen der Komponente kein Wert zugewiesen wurde.

Ohne takeUntil Abonnement weiterhin in einem angehaltenen Zustand, bis es seinen ersten Wert erhält. Da die Komponente jedoch bereits entfernt wurde, erhält sie den Wert nie und dies führt zu einem Speicherverlust.

6) Faules Laden


Versuchen Sie nach Möglichkeit, Module in einer Angular Anwendung nur dann zu laden, wenn sie verwendet werden.

Warum?


Dadurch wird die Größe der heruntergeladenen Anwendung verringert und die Ladezeit verkürzt.

Zu


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

Nachher


 // 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 {} 

Fortsetzung der Übersetzung im nächsten Artikel. Wenn jemand nicht warten möchte, dann ist hier ein Link zum Originalartikel.

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


All Articles