From ca3299ea5b00c7075d93871ec418e1527d390f8b Mon Sep 17 00:00:00 2001 From: Artur Androsovych Date: Fri, 17 Dec 2021 05:14:08 +0200 Subject: [PATCH] perf(module:carousel): do not run change detection on non-handled `keydown` events (#7097) --- components/carousel/carousel.component.ts | 52 ++++++++++++++--------- 1 file changed, 33 insertions(+), 19 deletions(-) diff --git a/components/carousel/carousel.component.ts b/components/carousel/carousel.component.ts index 674635ccd7..d96cf761a8 100644 --- a/components/carousel/carousel.component.ts +++ b/components/carousel/carousel.component.ts @@ -17,6 +17,7 @@ import { EventEmitter, Inject, Input, + NgZone, OnChanges, OnDestroy, OnInit, @@ -29,7 +30,7 @@ import { ViewChild, ViewEncapsulation } from '@angular/core'; -import { Subject } from 'rxjs'; +import { fromEvent, Subject } from 'rxjs'; import { takeUntil } from 'rxjs/operators'; import { NzConfigKey, NzConfigService, WithConfig } from 'ng-zorro-antd/core/config'; @@ -67,7 +68,6 @@ const NZ_CONFIG_MODULE_NAME: NzConfigKey = 'carousel'; #slickList class="slick-list" tabindex="-1" - (keydown)="onKeyDown($event)" (mousedown)="pointerDown($event)" (touchstart)="pointerDown($event)" > @@ -117,8 +117,8 @@ export class NzCarouselComponent implements AfterContentInit, AfterViewInit, OnD @ContentChildren(NzCarouselContentDirective) carouselContents!: QueryList; - @ViewChild('slickList', { static: false }) slickList?: ElementRef; - @ViewChild('slickTrack', { static: false }) slickTrack?: ElementRef; + @ViewChild('slickList', { static: true }) slickList!: ElementRef; + @ViewChild('slickTrack', { static: true }) slickTrack!: ElementRef; @Input() nzDotRender?: TemplateRef<{ $implicit: number }>; @Input() @WithConfig() nzEffect: NzCarouselEffects = 'scrollx'; @@ -172,6 +172,7 @@ export class NzCarouselComponent implements AfterContentInit, AfterViewInit, OnD constructor( elementRef: ElementRef, public readonly nzConfigService: NzConfigService, + private readonly ngZone: NgZone, private readonly renderer: Renderer2, private readonly cdr: ChangeDetectorRef, private readonly platform: Platform, @@ -186,13 +187,39 @@ export class NzCarouselComponent implements AfterContentInit, AfterViewInit, OnD this.el = elementRef.nativeElement; } ngOnInit(): void { + this.slickListEl = this.slickList!.nativeElement; + this.slickTrackEl = this.slickTrack!.nativeElement; + this.dir = this.directionality.value; - this.directionality.change?.pipe(takeUntil(this.destroy$)).subscribe((direction: Direction) => { + this.directionality.change.pipe(takeUntil(this.destroy$)).subscribe((direction: Direction) => { this.dir = direction; this.markContentActive(this.activeIndex); this.cdr.detectChanges(); }); + + this.ngZone.runOutsideAngular(() => { + fromEvent(this.slickListEl, 'keydown') + .pipe(takeUntil(this.destroy$)) + .subscribe(event => { + const { keyCode } = event; + + if (keyCode !== LEFT_ARROW && keyCode !== RIGHT_ARROW) { + return; + } + + event.preventDefault(); + + this.ngZone.run(() => { + if (keyCode === LEFT_ARROW) { + this.pre(); + } else { + this.next(); + } + this.cdr.markForCheck(); + }); + }); + }); } ngAfterContentInit(): void { @@ -200,10 +227,7 @@ export class NzCarouselComponent implements AfterContentInit, AfterViewInit, OnD } ngAfterViewInit(): void { - this.slickListEl = this.slickList!.nativeElement; - this.slickTrackEl = this.slickTrack!.nativeElement; - - this.carouselContents.changes.pipe(takeUntil(this.destroy$)).subscribe(() => { + this.carouselContents.changes.subscribe(() => { this.markContentActive(0); this.layout(); }); @@ -259,16 +283,6 @@ export class NzCarouselComponent implements AfterContentInit, AfterViewInit, OnD this.destroy$.complete(); } - onKeyDown(e: KeyboardEvent): void { - if (e.keyCode === LEFT_ARROW) { - e.preventDefault(); - this.pre(); - } else if (e.keyCode === RIGHT_ARROW) { - this.next(); - e.preventDefault(); - } - } - onLiClick = (index: number): void => { if (this.dir === 'rtl') { this.goTo(this.carouselContents.length - 1 - index);