I am very undecided whether to use BehaviorSubject to bind data to html. Below are two examples, the First sample binds normally, and the second one binds with "changeDetection: ChangeDetectionStrategy.OnPush" and "BehaviorSubject"
https://stackblitz.com/edit/angular-ivy-gbfqjo?file=src/app/app.component.ts
https://stackblitz.com/edit/angular-ivy-jgnqpt?file=src/app/app.component.ts
As seen in Console , The first method, (ChangeDetection is default and always running), it always calls setName function and logs "init", but in second method, setName is only calls when if $data is registered new value, because of "ChangeDetectionStrategy.OnPush" (dont need ChangeDetectorRef.detectChanges() because data$ already inited).
When should I use method 1 or method 2? Is there an important performance increase?
For example, which method should I use to show 100 data on the table (can be delete from table)?
Which one should I use to lazy load messages (like an infinite scroll)?
When should I use the BehaviorSubject (when just I need Observable) or should I always use it to bind data?
CodePudding user response:
First of all, using setName() method in the template is bad practice because it runs in every change detection and creates performance issues. so you can avoid this with Pure pipes.
if you use pure pipe and avoid using the method, the first approach is ok and works fine.
but you can use BehaviorSubject inside data services in order to share data in a reactive way between components and other services as well.
but ChangeDetectionStrategy.OnPush helps you to prevent some presentational components to be rendered each time change detection runs. for example, if a data or input changes in parent component and you have lots of chid component that are not affected with this change you can use this approach to avoid this components to be rendered and increase performance of your app
CodePudding user response:
public data = [
{ Id: 1, Name: 'A', formatedName: '' },
{ Id: 2, Name: 'B', formatedName: '' },
];
public setName(e: string) {
console.log('init');
return e '-' e;
}
ngOnInit() {
this.data.map((item) => {
item.formatedName = this.setName(item.Name);
return item;
});
}
<div *ngFor="let item of data">
<span [innerText]="item.Id"></span>
<span>{{ item.formatedName }}</span>
</div>
but the best practice is to use pipe
@Pipe({
name: 'customName',
})
export class CustomNamePipe implements PipeTransform {
transform(name: string): string {
return name '-' name;
}
}
<div *ngFor="let item of data">
<span [innerText]="item.Id"></span>
<span>{{ item.Name | customName }}</span>
</div>
