Skip to content

Commit c20bb80

Browse files
authored
perf(module:modal): do not run change detection on mouse events (#7169)
1 parent a6195b9 commit c20bb80

File tree

3 files changed

+47
-54
lines changed

3 files changed

+47
-54
lines changed

components/modal/modal-confirm-container.component.ts

Lines changed: 9 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import {
1515
EventEmitter,
1616
Inject,
1717
NgZone,
18+
OnInit,
1819
Optional,
1920
Output,
2021
Renderer2,
@@ -39,7 +40,6 @@ import { ModalOptions } from './modal-types';
3940
#modalElement
4041
role="document"
4142
class="ant-modal"
42-
(mousedown)="onMousedown()"
4343
[ngClass]="config.nzClassName!"
4444
[ngStyle]="config.nzStyle!"
4545
[style.width]="config?.nzWidth! | nzToCssUnit"
@@ -103,11 +103,10 @@ import { ModalOptions } from './modal-types';
103103
'[@modalContainer]': 'state',
104104
'(@modalContainer.start)': 'onAnimationStart($event)',
105105
'(@modalContainer.done)': 'onAnimationDone($event)',
106-
'(click)': 'onContainerClick($event)',
107-
'(mouseup)': 'onMouseup()'
106+
'(click)': 'onContainerClick($event)'
108107
}
109108
})
110-
export class NzModalConfirmContainerComponent extends BaseModalContainerComponent {
109+
export class NzModalConfirmContainerComponent extends BaseModalContainerComponent implements OnInit {
111110
@ViewChild(CdkPortalOutlet, { static: true }) portalOutlet!: CdkPortalOutlet;
112111
@ViewChild('modalElement', { static: true }) modalElementRef!: ElementRef<HTMLDivElement>;
113112
@Output() readonly cancelTriggered = new EventEmitter<void>();
@@ -117,7 +116,7 @@ export class NzModalConfirmContainerComponent extends BaseModalContainerComponen
117116
constructor(
118117
ngZone: NgZone,
119118
private i18n: NzI18nService,
120-
elementRef: ElementRef,
119+
host: ElementRef<HTMLElement>,
121120
focusTrapFactory: FocusTrapFactory,
122121
cdr: ChangeDetectorRef,
123122
render: Renderer2,
@@ -127,24 +126,17 @@ export class NzModalConfirmContainerComponent extends BaseModalContainerComponen
127126
@Optional() @Inject(DOCUMENT) document: NzSafeAny,
128127
@Optional() @Inject(ANIMATION_MODULE_TYPE) animationType: string
129128
) {
130-
super(
131-
ngZone,
132-
elementRef,
133-
focusTrapFactory,
134-
cdr,
135-
render,
136-
overlayRef,
137-
nzConfigService,
138-
config,
139-
document,
140-
animationType
141-
);
129+
super(ngZone, host, focusTrapFactory, cdr, render, overlayRef, nzConfigService, config, document, animationType);
142130

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

136+
ngOnInit(): void {
137+
this.setupMouseListeners(this.modalElementRef);
138+
}
139+
148140
onCancel(): void {
149141
this.cancelTriggered.emit();
150142
}

components/modal/modal-container.component.ts

Lines changed: 10 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import {
1414
ElementRef,
1515
Inject,
1616
NgZone,
17+
OnInit,
1718
Optional,
1819
Renderer2,
1920
ViewChild
@@ -35,7 +36,6 @@ import { ModalOptions } from './modal-types';
3536
#modalElement
3637
role="document"
3738
class="ant-modal"
38-
(mousedown)="onMousedown()"
3939
[ngClass]="config.nzClassName!"
4040
[ngStyle]="config.nzStyle!"
4141
[style.width]="config?.nzWidth! | nzToCssUnit"
@@ -71,16 +71,16 @@ import { ModalOptions } from './modal-types';
7171
'[@modalContainer]': 'state',
7272
'(@modalContainer.start)': 'onAnimationStart($event)',
7373
'(@modalContainer.done)': 'onAnimationDone($event)',
74-
'(click)': 'onContainerClick($event)',
75-
'(mouseup)': 'onMouseup()'
74+
'(click)': 'onContainerClick($event)'
7675
}
7776
})
78-
export class NzModalContainerComponent extends BaseModalContainerComponent {
77+
export class NzModalContainerComponent extends BaseModalContainerComponent implements OnInit {
7978
@ViewChild(CdkPortalOutlet, { static: true }) portalOutlet!: CdkPortalOutlet;
8079
@ViewChild('modalElement', { static: true }) modalElementRef!: ElementRef<HTMLDivElement>;
80+
8181
constructor(
8282
ngZone: NgZone,
83-
elementRef: ElementRef,
83+
host: ElementRef<HTMLElement>,
8484
focusTrapFactory: FocusTrapFactory,
8585
cdr: ChangeDetectorRef,
8686
render: Renderer2,
@@ -90,17 +90,10 @@ export class NzModalContainerComponent extends BaseModalContainerComponent {
9090
@Optional() @Inject(DOCUMENT) document: NzSafeAny,
9191
@Optional() @Inject(ANIMATION_MODULE_TYPE) animationType: string
9292
) {
93-
super(
94-
ngZone,
95-
elementRef,
96-
focusTrapFactory,
97-
cdr,
98-
render,
99-
overlayRef,
100-
nzConfigService,
101-
config,
102-
document,
103-
animationType
104-
);
93+
super(ngZone, host, focusTrapFactory, cdr, render, overlayRef, nzConfigService, config, document, animationType);
94+
}
95+
96+
ngOnInit(): void {
97+
this.setupMouseListeners(this.modalElementRef);
10598
}
10699
}

components/modal/modal-container.directive.ts

Lines changed: 28 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ import {
1919
OnDestroy,
2020
Renderer2
2121
} from '@angular/core';
22-
import { Subject } from 'rxjs';
22+
import { fromEvent, Subject } from 'rxjs';
2323
import { takeUntil } from 'rxjs/operators';
2424

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

7171
constructor(
7272
protected ngZone: NgZone,
73-
protected elementRef: ElementRef,
73+
protected host: ElementRef<HTMLElement>,
7474
protected focusTrapFactory: FocusTrapFactory,
7575
public cdr: ChangeDetectorRef,
7676
protected render: Renderer2,
@@ -98,18 +98,6 @@ export class BaseModalContainerComponent extends BasePortalOutlet implements OnD
9898
}
9999
}
100100

101-
onMousedown(): void {
102-
this.mouseDown = true;
103-
}
104-
105-
onMouseup(): void {
106-
if (this.mouseDown) {
107-
setTimeout(() => {
108-
this.mouseDown = false;
109-
});
110-
}
111-
}
112-
113101
onCloseClick(): void {
114102
this.cancelTriggered.emit();
115103
}
@@ -142,7 +130,7 @@ export class BaseModalContainerComponent extends BasePortalOutlet implements OnD
142130
}
143131

144132
getNativeElement(): HTMLElement {
145-
return this.elementRef.nativeElement;
133+
return this.host.nativeElement;
146134
}
147135

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

164152
private savePreviouslyFocusedElement(): void {
165153
if (!this.focusTrap) {
166-
this.focusTrap = this.focusTrapFactory.create(this.elementRef.nativeElement);
154+
this.focusTrap = this.focusTrapFactory.create(this.host.nativeElement);
167155
}
168156

169157
if (this.document) {
170158
this.elementFocusedBeforeModalWasOpened = this.document.activeElement as HTMLElement;
171-
if (this.elementRef.nativeElement.focus) {
172-
this.ngZone.runOutsideAngular(() => Promise.resolve().then(() => this.elementRef.nativeElement.focus()));
159+
if (this.host.nativeElement.focus) {
160+
this.ngZone.runOutsideAngular(() => Promise.resolve().then(() => this.host.nativeElement.focus()));
173161
}
174162
}
175163
}
176164

177165
private trapFocus(): void {
178-
const element = this.elementRef.nativeElement;
166+
const element = this.host.nativeElement;
179167

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

198186
if (
199187
!activeElement ||
@@ -337,4 +325,24 @@ export class BaseModalContainerComponent extends BasePortalOutlet implements OnD
337325
this.destroy$.next();
338326
this.destroy$.complete();
339327
}
328+
329+
protected setupMouseListeners(modalContainer: ElementRef<HTMLElement>): void {
330+
this.ngZone.runOutsideAngular(() => {
331+
fromEvent(this.host.nativeElement, 'mouseup')
332+
.pipe(takeUntil(this.destroy$))
333+
.subscribe(() => {
334+
if (this.mouseDown) {
335+
setTimeout(() => {
336+
this.mouseDown = false;
337+
});
338+
}
339+
});
340+
341+
fromEvent(modalContainer.nativeElement, 'mousedown')
342+
.pipe(takeUntil(this.destroy$))
343+
.subscribe(() => {
344+
this.mouseDown = true;
345+
});
346+
});
347+
}
340348
}

0 commit comments

Comments
 (0)