From 345357b0d3a1cf46bdc559047cb26fa770b1bf7c Mon Sep 17 00:00:00 2001 From: arturovt Date: Fri, 19 Nov 2021 04:52:49 +0200 Subject: [PATCH] perf(cdk/scrolling): do not run change detection if there are no `viewChange` listeners --- src/cdk/scrolling/virtual-for-of.ts | 4 +- .../scrolling/virtual-scroll-viewport.spec.ts | 38 +++++++++++++++++++ 2 files changed, 41 insertions(+), 1 deletion(-) diff --git a/src/cdk/scrolling/virtual-for-of.ts b/src/cdk/scrolling/virtual-for-of.ts index be8a57a4d77a..7cf5be830121 100644 --- a/src/cdk/scrolling/virtual-for-of.ts +++ b/src/cdk/scrolling/virtual-for-of.ts @@ -199,7 +199,9 @@ export class CdkVirtualForOf }); this._viewport.renderedRangeStream.pipe(takeUntil(this._destroyed)).subscribe(range => { this._renderedRange = range; - ngZone.run(() => this.viewChange.next(this._renderedRange)); + if (this.viewChange.observers.length) { + ngZone.run(() => this.viewChange.next(this._renderedRange)); + } this._onRenderedDataChange(); }); this._viewport.attach(this); diff --git a/src/cdk/scrolling/virtual-scroll-viewport.spec.ts b/src/cdk/scrolling/virtual-scroll-viewport.spec.ts index 0ad60eea3034..0698ebf32d15 100644 --- a/src/cdk/scrolling/virtual-scroll-viewport.spec.ts +++ b/src/cdk/scrolling/virtual-scroll-viewport.spec.ts @@ -15,6 +15,7 @@ import { ViewEncapsulation, Directive, ViewContainerRef, + ApplicationRef, } from '@angular/core'; import { waitForAsync, @@ -786,6 +787,43 @@ describe('CdkVirtualScrollViewport', () => { } }).not.toThrow(); })); + + describe('viewChange change detection behavior', () => { + let appRef: ApplicationRef; + + beforeEach(inject([ApplicationRef], (ar: ApplicationRef) => { + appRef = ar; + })); + + it('should not run change detection if there are no viewChange listeners', fakeAsync(() => { + finishInit(fixture); + testComponent.items = Array(10).fill(0); + fixture.detectChanges(); + flush(); + + spyOn(appRef, 'tick'); + + viewport.scrollToIndex(5); + triggerScroll(viewport); + + expect(appRef.tick).not.toHaveBeenCalled(); + })); + + it('should run change detection if there are any viewChange listeners', fakeAsync(() => { + testComponent.virtualForOf.viewChange.subscribe(); + finishInit(fixture); + testComponent.items = Array(10).fill(0); + fixture.detectChanges(); + flush(); + + spyOn(appRef, 'tick'); + + viewport.scrollToIndex(5); + triggerScroll(viewport); + + expect(appRef.tick).toHaveBeenCalledTimes(1); + })); + }); }); describe('with RTL direction', () => {