I have a large array that I am using in a ponent (ponent A) with *ngFor
with a nested *ngFor
.
Component B initialises a jquery plugin which registers a document mousemove
event handler, I am using this.zone.runOutsideAngular
to init the plugin and I am calling this.ref.detectChanges()
in the callback as I need to update the UI on mousemove
inside the ponent B.
Component A is not a child of ponent B.
As soon as the ponent A is rendered change detection bees very slow. the array does not change and I am using the ChangeDetectionStrategy.OnPush
strategy for ponent A but when I fire ref.detectChanges()
inside ponent B, ngDoCheck
gets called on ponent A and I can see a noticeable jank on mousemove
.
Is there a way to tell angular to pletely ignore the large array of items in ponent A and allow me to handle when the UI should be updated? I thought that using ChangeDetectionStrategy.OnPush
would give me what I need but I have tried removing all @Input()
s from ponent A and anytime I call this.ref.detectChanges()
inside ponent B it is still firing ngDoCheck
and it is obvious that this is very slow.
I can scroll through the list of items no issue, but it is when I am triggering the detectChanges
inside the mousemove
on ponent B that is causing the issue. I know I could manually update the DOM but I think this would just be a workaround as it would only address the jank on mousemove and not the issue around the change detection being slow.
I have a large array that I am using in a ponent (ponent A) with *ngFor
with a nested *ngFor
.
Component B initialises a jquery plugin which registers a document mousemove
event handler, I am using this.zone.runOutsideAngular
to init the plugin and I am calling this.ref.detectChanges()
in the callback as I need to update the UI on mousemove
inside the ponent B.
Component A is not a child of ponent B.
As soon as the ponent A is rendered change detection bees very slow. the array does not change and I am using the ChangeDetectionStrategy.OnPush
strategy for ponent A but when I fire ref.detectChanges()
inside ponent B, ngDoCheck
gets called on ponent A and I can see a noticeable jank on mousemove
.
Is there a way to tell angular to pletely ignore the large array of items in ponent A and allow me to handle when the UI should be updated? I thought that using ChangeDetectionStrategy.OnPush
would give me what I need but I have tried removing all @Input()
s from ponent A and anytime I call this.ref.detectChanges()
inside ponent B it is still firing ngDoCheck
and it is obvious that this is very slow.
I can scroll through the list of items no issue, but it is when I am triggering the detectChanges
inside the mousemove
on ponent B that is causing the issue. I know I could manually update the DOM but I think this would just be a workaround as it would only address the jank on mousemove and not the issue around the change detection being slow.
- use 'trackBy : yourTrackByFn' in *ngFor . This will solve your issue, as whenever ChangeDetection happend it execute life cycle event for that ponent every time which impact on performance. – Amol Bhor Commented Mar 23, 2018 at 14:53
2 Answers
Reset to default 4I have got to the bottom of this issue.
The problem was that inside ponent A for the nested *ngFor I was using a child ponent to render each sub item which meant that although I was using the ChangeDetectionStrategy.OnPush strategy, it still required a ref check for each item.
I have now moved the html from the child ponent into ponent A directly and this has had a huge impact on performance.
this.ref.detach()
to remove the detector from from the tree pletely, that should stop the checking. Then you can still call detectChanges
to do it manually, and reattach
to bring it back online.
Maybe also debouncing the mousemoves (rxjs debounceTime()) might help, unless you really need to track every mousemove?
One more optimization if you already didn't, add trackBy: yourTrackByFn
to the ngFor(s).