Skip to content

Commit

Permalink
perf(module:modal): do not run change detection on mouse events (#7169)
Browse files Browse the repository at this point in the history
  • Loading branch information
arturovt committed Jan 13, 2022
1 parent a6195b9 commit c20bb80
Show file tree
Hide file tree
Showing 3 changed files with 47 additions and 54 deletions.
26 changes: 9 additions & 17 deletions components/modal/modal-confirm-container.component.ts
Expand Up @@ -15,6 +15,7 @@ import {
EventEmitter,
Inject,
NgZone,
OnInit,
Optional,
Output,
Renderer2,
Expand All @@ -39,7 +40,6 @@ import { ModalOptions } from './modal-types';
#modalElement
role="document"
class="ant-modal"
(mousedown)="onMousedown()"
[ngClass]="config.nzClassName!"
[ngStyle]="config.nzStyle!"
[style.width]="config?.nzWidth! | nzToCssUnit"
Expand Down Expand Up @@ -103,11 +103,10 @@ import { ModalOptions } from './modal-types';
'[@modalContainer]': 'state',
'(@modalContainer.start)': 'onAnimationStart($event)',
'(@modalContainer.done)': 'onAnimationDone($event)',
'(click)': 'onContainerClick($event)',
'(mouseup)': 'onMouseup()'
'(click)': 'onContainerClick($event)'
}
})
export class NzModalConfirmContainerComponent extends BaseModalContainerComponent {
export class NzModalConfirmContainerComponent extends BaseModalContainerComponent implements OnInit {
@ViewChild(CdkPortalOutlet, { static: true }) portalOutlet!: CdkPortalOutlet;
@ViewChild('modalElement', { static: true }) modalElementRef!: ElementRef<HTMLDivElement>;
@Output() readonly cancelTriggered = new EventEmitter<void>();
Expand All @@ -117,7 +116,7 @@ export class NzModalConfirmContainerComponent extends BaseModalContainerComponen
constructor(
ngZone: NgZone,
private i18n: NzI18nService,
elementRef: ElementRef,
host: ElementRef<HTMLElement>,
focusTrapFactory: FocusTrapFactory,
cdr: ChangeDetectorRef,
render: Renderer2,
Expand All @@ -127,24 +126,17 @@ export class NzModalConfirmContainerComponent extends BaseModalContainerComponen
@Optional() @Inject(DOCUMENT) document: NzSafeAny,
@Optional() @Inject(ANIMATION_MODULE_TYPE) animationType: string
) {
super(
ngZone,
elementRef,
focusTrapFactory,
cdr,
render,
overlayRef,
nzConfigService,
config,
document,
animationType
);
super(ngZone, host, focusTrapFactory, cdr, render, overlayRef, nzConfigService, config, document, animationType);

this.i18n.localeChange.pipe(takeUntil(this.destroy$)).subscribe(() => {
this.locale = this.i18n.getLocaleData('Modal');
});
}

ngOnInit(): void {
this.setupMouseListeners(this.modalElementRef);
}

onCancel(): void {
this.cancelTriggered.emit();
}
Expand Down
27 changes: 10 additions & 17 deletions components/modal/modal-container.component.ts
Expand Up @@ -14,6 +14,7 @@ import {
ElementRef,
Inject,
NgZone,
OnInit,
Optional,
Renderer2,
ViewChild
Expand All @@ -35,7 +36,6 @@ import { ModalOptions } from './modal-types';
#modalElement
role="document"
class="ant-modal"
(mousedown)="onMousedown()"
[ngClass]="config.nzClassName!"
[ngStyle]="config.nzStyle!"
[style.width]="config?.nzWidth! | nzToCssUnit"
Expand Down Expand Up @@ -71,16 +71,16 @@ import { ModalOptions } from './modal-types';
'[@modalContainer]': 'state',
'(@modalContainer.start)': 'onAnimationStart($event)',
'(@modalContainer.done)': 'onAnimationDone($event)',
'(click)': 'onContainerClick($event)',
'(mouseup)': 'onMouseup()'
'(click)': 'onContainerClick($event)'
}
})
export class NzModalContainerComponent extends BaseModalContainerComponent {
export class NzModalContainerComponent extends BaseModalContainerComponent implements OnInit {
@ViewChild(CdkPortalOutlet, { static: true }) portalOutlet!: CdkPortalOutlet;
@ViewChild('modalElement', { static: true }) modalElementRef!: ElementRef<HTMLDivElement>;

constructor(
ngZone: NgZone,
elementRef: ElementRef,
host: ElementRef<HTMLElement>,
focusTrapFactory: FocusTrapFactory,
cdr: ChangeDetectorRef,
render: Renderer2,
Expand All @@ -90,17 +90,10 @@ export class NzModalContainerComponent extends BaseModalContainerComponent {
@Optional() @Inject(DOCUMENT) document: NzSafeAny,
@Optional() @Inject(ANIMATION_MODULE_TYPE) animationType: string
) {
super(
ngZone,
elementRef,
focusTrapFactory,
cdr,
render,
overlayRef,
nzConfigService,
config,
document,
animationType
);
super(ngZone, host, focusTrapFactory, cdr, render, overlayRef, nzConfigService, config, document, animationType);
}

ngOnInit(): void {
this.setupMouseListeners(this.modalElementRef);
}
}
48 changes: 28 additions & 20 deletions components/modal/modal-container.directive.ts
Expand Up @@ -19,7 +19,7 @@ import {
OnDestroy,
Renderer2
} from '@angular/core';
import { Subject } from 'rxjs';
import { fromEvent, Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';

import { NzConfigService } from 'ng-zorro-antd/core/config';
Expand Down Expand Up @@ -70,7 +70,7 @@ export class BaseModalContainerComponent extends BasePortalOutlet implements OnD

constructor(
protected ngZone: NgZone,
protected elementRef: ElementRef,
protected host: ElementRef<HTMLElement>,
protected focusTrapFactory: FocusTrapFactory,
public cdr: ChangeDetectorRef,
protected render: Renderer2,
Expand Down Expand Up @@ -98,18 +98,6 @@ export class BaseModalContainerComponent extends BasePortalOutlet implements OnD
}
}

onMousedown(): void {
this.mouseDown = true;
}

onMouseup(): void {
if (this.mouseDown) {
setTimeout(() => {
this.mouseDown = false;
});
}
}

onCloseClick(): void {
this.cancelTriggered.emit();
}
Expand Down Expand Up @@ -142,7 +130,7 @@ export class BaseModalContainerComponent extends BasePortalOutlet implements OnD
}

getNativeElement(): HTMLElement {
return this.elementRef.nativeElement;
return this.host.nativeElement;
}

private animationDisabled(): boolean {
Expand All @@ -163,19 +151,19 @@ export class BaseModalContainerComponent extends BasePortalOutlet implements OnD

private savePreviouslyFocusedElement(): void {
if (!this.focusTrap) {
this.focusTrap = this.focusTrapFactory.create(this.elementRef.nativeElement);
this.focusTrap = this.focusTrapFactory.create(this.host.nativeElement);
}

if (this.document) {
this.elementFocusedBeforeModalWasOpened = this.document.activeElement as HTMLElement;
if (this.elementRef.nativeElement.focus) {
this.ngZone.runOutsideAngular(() => Promise.resolve().then(() => this.elementRef.nativeElement.focus()));
if (this.host.nativeElement.focus) {
this.ngZone.runOutsideAngular(() => Promise.resolve().then(() => this.host.nativeElement.focus()));
}
}
}

private trapFocus(): void {
const element = this.elementRef.nativeElement;
const element = this.host.nativeElement;

if (this.config.nzAutofocus) {
this.focusTrap.focusInitialElementWhenReady();
Expand All @@ -193,7 +181,7 @@ export class BaseModalContainerComponent extends BasePortalOutlet implements OnD
// We need the extra check, because IE can set the `activeElement` to null in some cases.
if (toFocus && typeof toFocus.focus === 'function') {
const activeElement = this.document.activeElement as Element;
const element = this.elementRef.nativeElement;
const element = this.host.nativeElement;

if (
!activeElement ||
Expand Down Expand Up @@ -337,4 +325,24 @@ export class BaseModalContainerComponent extends BasePortalOutlet implements OnD
this.destroy$.next();
this.destroy$.complete();
}

protected setupMouseListeners(modalContainer: ElementRef<HTMLElement>): void {
this.ngZone.runOutsideAngular(() => {
fromEvent(this.host.nativeElement, 'mouseup')
.pipe(takeUntil(this.destroy$))
.subscribe(() => {
if (this.mouseDown) {
setTimeout(() => {
this.mouseDown = false;
});
}
});

fromEvent(modalContainer.nativeElement, 'mousedown')
.pipe(takeUntil(this.destroy$))
.subscribe(() => {
this.mouseDown = true;
});
});
}
}

0 comments on commit c20bb80

Please sign in to comment.