ngFor
to traverse arrays in templates, use this construct with the trackBy
function, which returns a unique identifier for each element.trackBy
, the system will know which element has changed and will make changes to the DOM that relate only to that particular element. Details about this can be found here . <li *ngFor="let item of items;">{{ item }}</li>
// <li *ngFor="let item of items; trackBy: trackByFn">{{ item }}</li> // trackByFn(index, item) { return item.id; // id, }
const
.let
and const
keywords clarifies the intent regarding the use of entities declared with their help. In addition, this approach makes it easier to recognize problems caused by accidentally overwriting constant values. In such a situation, a compilation error is generated. In addition, it improves the readability of the code. let car = 'ludicrous car'; let myCar = `My ${car}`; let yourCar = `Your ${car}; if (iHaveMoreThanOneCar) { myCar = `${myCar}s`; } if (youHaveMoreThanOneCar) { yourCar = `${youCar}s`; }
// car , car const car = 'ludicrous car'; let myCar = `My ${car}`; let yourCar = `Your ${car}; if (iHaveMoreThanOneCar) { myCar = `${myCar}s`; } if (youHaveMoreThanOneCar) { yourCar = `${youCar}s`; }
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) );
API_FIX
(which resembles the TODO
tag), and tag them with fixes. This makes finding such fixes easier. // <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) );
take
, takeUntil
and so on. iAmAnObservable .pipe( map(value => value.item) ) .subscribe(item => this.textToDisplay = item);
takeUntil
operator if you want to monitor changes in an object until another observed object generates a certain value: 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
is a pattern used to control the removal of subscriptions to many of the observed objects in a component.take
if you only need the first value returned by the observed object: iAmAnObservable .pipe( map(value => value.item), take(1), takeUntil(this._destroyed$) ) .subscribe(item => this.textToDisplay = item);
takeUntil
with take
. This is done in order to avoid memory leaks caused by the fact that the subscription did not result in a value before the component was destroyed. If the takeUntil
function were not used takeUntil
, the subscription would exist before the first value was received, but since the component would have already been destroyed, this value would never have been received, which would lead to a memory leak.switchMap
when you need to ignore the previous dispatched action when a new action arrives.mergeMap
if you need to handle all dispatched actions in parallel.concatMap
when actions need to be processed one after another, in the order they are received.exhaustMap
in situations where, during the processing of previously received actions, you need to ignore new ones. // 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 {}
subscribe
blocks of other monitored objects. Instead, use the appropriate operators to chain the commands together. Among such operators can be noted withLatestFrom
and combineLatest
. Consider the examples, and then comment on them. firstObservable$.pipe( take(1) ) .subscribe(firstValue => { secondObservable$.pipe( take(1) ) .subscribe(secondValue => { console.log(`Combined values are: ${firstValue} & ${secondValue}`); }); });
firstObservable$.pipe( withLatestFrom(secondObservable$), first() ) .subscribe(([firstValue, secondValue]) => { console.log(`Combined values are: ${firstValue} & ${secondValue}`); });
firstObservable
, then the system will wait for the operation to complete, and only after that will work with the second observed object. If these objects are network requests, then it will look like synchronous execution of requests.any
. const x = 1; const y = 'a'; const z = x + y; console.log(`Value of z is: ${z}` // Value of z is 1a
y
is a number here, but our program does not know about it, so it displays something that looks wrong, but does not give any error messages. Similar problems can be avoided by assigning appropriate types to variables and constants. const x: number = 1; const y: number = 'a'; const z: number = x + y; // : Type '"a"' is not assignable to type 'number'. const y:number
public ngOnInit (): void { let myFlashObject = { name: 'My cool name', age: 'My cool age', loc: 'My cool location' } this.processObject(myFlashObject); } public processObject(myObject: any): void { console.log(`Name: ${myObject.name}`); console.log(`Age: ${myObject.age}`); console.log(`Location: ${myObject.loc}`); } // Name: My cool name Age: My cool age Location: My cool location
myFlashObject
object, the name of the property loc
on location
and made an error during code editing: public ngOnInit (): void { let myFlashObject = { name: 'My cool name', age: 'My cool age', location: 'My cool location' } this.processObject(myFlashObject); } public processObject(myObject: any): void { console.log(`Name: ${myObject.name}`); console.log(`Age: ${myObject.age}`); console.log(`Location: ${myObject.loc}`); } // Name: My cool name Age: My cool age Location: undefined
myFlashObject
, then in our case the system assumes that the value of the loc
property of myFlashObject
is undefined
. She does not think that loc
can be an invalid property name.myFlashObject
object, then in a similar situation we will see, when compiling the code, a wonderful error message: type FlashObject = { name: string, age: string, location: string } public ngOnInit (): void { let myFlashObject: FlashObject = { name: 'My cool name', age: 'My cool age', // Type '{ name: string; age: string; loc: string; }' is not assignable to type 'FlashObjectType'. Object literal may only specify known properties, and 'loc' does not exist in type 'FlashObjectType'. loc: 'My cool location' } this.processObject(myFlashObject); } public processObject(myObject: FlashObject): void { console.log(`Name: ${myObject.name}`); console.log(`Age: ${myObject.age}`) // Property 'loc' does not exist on type 'FlashObjectType'. console.log(`Location: ${myObject.loc}`); }
strict:true
option in the tsconfig.json
file to enable strict type checking.tslint.json
file in order to organize the checking of code according to certain rules. public ngOnInit (): void { console.log('I am a naughty console log message'); console.warn('I am a naughty console warning message'); console.error('I am a naughty console error message'); } // . , : I am a naughty console message I am a naughty console warning message I am a naughty console error message
// tslint.json { "rules": { ....... "no-console": [ true, "log", // console.log "warn" // console.warn ] } } // ..component.ts public ngOnInit (): void { console.log('I am a naughty console log message'); console.warn('I am a naughty console warning message'); console.error('I am a naughty console error message'); } // . console.log and console.warn console.error, Calls to 'console.log' are not allowed. Calls to 'console.warn' are not allowed.
Source: https://habr.com/ru/post/425661/
All Articles