Skip to content

Commit 1171460

Browse files
authored
perf(module:date-picker): do not trigger change detection on mousedown (#7860)
1 parent ff36981 commit 1171460

File tree

1 file changed

+29
-28
lines changed

1 file changed

+29
-28
lines changed

components/date-picker/date-picker.component.ts

Lines changed: 29 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,8 @@ import {
2626
Host,
2727
Inject,
2828
Input,
29+
NgZone,
2930
OnChanges,
30-
OnDestroy,
3131
OnInit,
3232
Optional,
3333
Output,
@@ -40,7 +40,7 @@ import {
4040
ViewEncapsulation
4141
} from '@angular/core';
4242
import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';
43-
import { of as observableOf, Subject } from 'rxjs';
43+
import { fromEvent, of as observableOf } from 'rxjs';
4444
import { distinctUntilChanged, map, takeUntil, withLatestFrom } from 'rxjs/operators';
4545

4646
import { NzResizeObserver } from 'ng-zorro-antd/cdk/resize-observer';
@@ -49,6 +49,7 @@ import { NzConfigKey, NzConfigService, WithConfig } from 'ng-zorro-antd/core/con
4949
import { NzFormNoStatusService, NzFormStatusService } from 'ng-zorro-antd/core/form';
5050
import { NzNoAnimationDirective } from 'ng-zorro-antd/core/no-animation';
5151
import { DATE_PICKER_POSITION_MAP, DEFAULT_DATE_PICKER_POSITIONS } from 'ng-zorro-antd/core/overlay';
52+
import { NzDestroyService } from 'ng-zorro-antd/core/services';
5253
import { CandyDate, cloneDate, CompatibleValue, wrongSortOrder } from 'ng-zorro-antd/core/time';
5354
import {
5455
BooleanInput,
@@ -241,6 +242,7 @@ export type NzPlacement = 'bottomLeft' | 'bottomRight' | 'topLeft' | 'topRight';
241242
'(click)': 'onClickInputBox($event)'
242243
},
243244
providers: [
245+
NzDestroyService,
244246
DatePickerService,
245247
{
246248
provide: NG_VALUE_ACCESSOR,
@@ -250,7 +252,7 @@ export type NzPlacement = 'bottomLeft' | 'bottomRight' | 'topLeft' | 'topRight';
250252
],
251253
animations: [slideMotion]
252254
})
253-
export class NzDatePickerComponent implements OnInit, OnChanges, OnDestroy, AfterViewInit, ControlValueAccessor {
255+
export class NzDatePickerComponent implements OnInit, OnChanges, AfterViewInit, ControlValueAccessor {
254256
readonly _nzModuleName: NzConfigKey = NZ_CONFIG_MODULE_NAME;
255257
static ngAcceptInputType_nzAllowClear: BooleanInput;
256258
static ngAcceptInputType_nzAutoFocus: BooleanInput;
@@ -274,7 +276,6 @@ export class NzDatePickerComponent implements OnInit, OnChanges, OnDestroy, Afte
274276
hasFeedback: boolean = false;
275277

276278
public panelMode: NzDateMode | NzDateMode[] = 'date';
277-
private destroyed$: Subject<void> = new Subject();
278279
private isCustomPlaceHolder: boolean = false;
279280
private isCustomFormat: boolean = false;
280281
private showTime: SupportTimeOptions | boolean = false;
@@ -358,23 +359,33 @@ export class NzDatePickerComponent implements OnInit, OnChanges, OnDestroy, Afte
358359
if (this.isRange && this.platform.isBrowser) {
359360
this.nzResizeObserver
360361
.observe(this.elementRef)
361-
.pipe(takeUntil(this.destroyed$))
362+
.pipe(takeUntil(this.destroy$))
362363
.subscribe(() => {
363364
this.updateInputWidthAndArrowLeft();
364365
});
365366
}
366367

367-
this.datePickerService.inputPartChange$.pipe(takeUntil(this.destroyed$)).subscribe(partType => {
368+
this.datePickerService.inputPartChange$.pipe(takeUntil(this.destroy$)).subscribe(partType => {
368369
if (partType) {
369370
this.datePickerService.activeInput = partType;
370371
}
371372
this.focus();
372373
this.updateInputWidthAndArrowLeft();
373374
});
374375

375-
// prevent mousedown event to trigger focusout event when click in date picker
376-
// see: https://github.com/NG-ZORRO/ng-zorro-antd/issues/7450
377-
this.elementRef.nativeElement.addEventListener('mousedown', this.onMouseDown);
376+
if (this.platform.isBrowser) {
377+
this.ngZone.runOutsideAngular(() =>
378+
// prevent mousedown event to trigger focusout event when click in date picker
379+
// see: https://github.com/NG-ZORRO/ng-zorro-antd/issues/7450
380+
fromEvent(this.elementRef.nativeElement, 'mousedown')
381+
.pipe(takeUntil(this.destroy$))
382+
.subscribe(event => {
383+
if ((event.target as HTMLInputElement).tagName.toLowerCase() !== 'input') {
384+
event.preventDefault();
385+
}
386+
})
387+
);
388+
}
378389
}
379390

380391
updateInputWidthAndArrowLeft(): void {
@@ -413,12 +424,6 @@ export class NzDatePickerComponent implements OnInit, OnChanges, OnDestroy, Afte
413424
}
414425
}
415426

416-
onMouseDown(event: Event): void {
417-
if ((event.target as HTMLInputElement).tagName.toLowerCase() !== 'input') {
418-
event.preventDefault();
419-
}
420-
}
421-
422427
onFocus(event: FocusEvent, partType?: RangePartType): void {
423428
event.preventDefault();
424429
if (partType) {
@@ -430,7 +435,7 @@ export class NzDatePickerComponent implements OnInit, OnChanges, OnDestroy, Afte
430435
// blur event has not the relatedTarget in IE11, use focusout instead.
431436
onFocusout(event: FocusEvent): void {
432437
event.preventDefault();
433-
if (!this.elementRef.nativeElement.contains(event.relatedTarget)) {
438+
if (!this.elementRef.nativeElement.contains(<Node>event.relatedTarget)) {
434439
this.checkAndClose();
435440
}
436441
this.renderClass(false);
@@ -596,10 +601,12 @@ export class NzDatePickerComponent implements OnInit, OnChanges, OnDestroy, Afte
596601
protected i18n: NzI18nService,
597602
protected cdr: ChangeDetectorRef,
598603
private renderer: Renderer2,
599-
private elementRef: ElementRef,
604+
private ngZone: NgZone,
605+
private elementRef: ElementRef<HTMLElement>,
600606
private dateHelper: DateHelperService,
601607
private nzResizeObserver: NzResizeObserver,
602608
private platform: Platform,
609+
private destroy$: NzDestroyService,
603610
@Inject(DOCUMENT) doc: NzSafeAny,
604611
@Optional() private directionality: Directionality,
605612
@Host() @Optional() public noAnimation?: NzNoAnimationDirective,
@@ -618,21 +625,21 @@ export class NzDatePickerComponent implements OnInit, OnChanges, OnDestroy, Afte
618625
}),
619626
withLatestFrom(this.nzFormNoStatusService ? this.nzFormNoStatusService.noFormStatus : observableOf(false)),
620627
map(([{ status, hasFeedback }, noStatus]) => ({ status: noStatus ? '' : status, hasFeedback })),
621-
takeUntil(this.destroyed$)
628+
takeUntil(this.destroy$)
622629
)
623630
.subscribe(({ status, hasFeedback }) => {
624631
this.setStatusStyles(status, hasFeedback);
625632
});
626633

627634
// Subscribe the every locale change if the nzLocale is not handled by user
628635
if (!this.nzLocale) {
629-
this.i18n.localeChange.pipe(takeUntil(this.destroyed$)).subscribe(() => this.setLocale());
636+
this.i18n.localeChange.pipe(takeUntil(this.destroy$)).subscribe(() => this.setLocale());
630637
}
631638

632639
// Default value
633640
this.datePickerService.isRange = this.isRange;
634641
this.datePickerService.initValue(true);
635-
this.datePickerService.emitValue$.pipe(takeUntil(this.destroyed$)).subscribe(() => {
642+
this.datePickerService.emitValue$.pipe(takeUntil(this.destroy$)).subscribe(() => {
636643
const value = this.datePickerService.value;
637644
const datePickerPreviousValue = this.datePickerService.initialValue;
638645

@@ -675,15 +682,15 @@ export class NzDatePickerComponent implements OnInit, OnChanges, OnDestroy, Afte
675682
this.close();
676683
});
677684

678-
this.directionality.change?.pipe(takeUntil(this.destroyed$)).subscribe((direction: Direction) => {
685+
this.directionality.change?.pipe(takeUntil(this.destroy$)).subscribe((direction: Direction) => {
679686
this.dir = direction;
680687
this.cdr.detectChanges();
681688
});
682689
this.dir = this.directionality.value;
683690
this.inputValue = this.isRange ? ['', ''] : '';
684691
this.setModeAndFormat();
685692

686-
this.datePickerService.valueChange$.pipe(takeUntil(this.destroyed$)).subscribe(() => {
693+
this.datePickerService.valueChange$.pipe(takeUntil(this.destroy$)).subscribe(() => {
687694
this.updateInputValue();
688695
});
689696
}
@@ -727,12 +734,6 @@ export class NzDatePickerComponent implements OnInit, OnChanges, OnDestroy, Afte
727734
}
728735
}
729736

730-
ngOnDestroy(): void {
731-
this.destroyed$.next();
732-
this.destroyed$.complete();
733-
this.elementRef.nativeElement.removeEventListener('mousedown', this.onMouseDown);
734-
}
735-
736737
setModeAndFormat(): void {
737738
const inputFormats: { [key in NzDateMode]?: string } = {
738739
year: 'yyyy',

0 commit comments

Comments
 (0)