Skip to content

Commit 12feff7

Browse files
crisbetoandrewseguin
authored andcommitted
perf(ripple): use passive event listeners (#8719)
Switches all of the ripple-related event listeners to be passive for improved performance and to prevent Chrome from logging warnings for almost every Material component.
1 parent 7c84490 commit 12feff7

File tree

2 files changed

+16
-13
lines changed

2 files changed

+16
-13
lines changed

src/cdk/platform/features.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ let supportsPassiveEvents: boolean;
1414
* See: https://github.com/WICG/EventListenerOptions/blob/gh-pages/explainer.md
1515
*/
1616
export function supportsPassiveEventListeners(): boolean {
17-
if (supportsPassiveEvents == null) {
17+
if (supportsPassiveEvents == null && typeof window !== 'undefined') {
1818
try {
1919
window.addEventListener('test', null!, Object.defineProperty({}, 'passive', {
2020
get: () => supportsPassiveEvents = true

src/lib/core/ripple/ripple-renderer.ts

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,8 @@
55
* Use of this source code is governed by an MIT-style license that can be
66
* found in the LICENSE file at https://angular.io/license
77
*/
8-
98
import {ElementRef, NgZone} from '@angular/core';
10-
import {Platform} from '@angular/cdk/platform';
9+
import {Platform, supportsPassiveEventListeners} from '@angular/cdk/platform';
1110
import {RippleRef, RippleState} from './ripple-ref';
1211

1312

@@ -58,6 +57,9 @@ export class RippleRenderer {
5857
/** Time in milliseconds when the last touchstart event happened. */
5958
private _lastTouchStartEvent: number;
6059

60+
/** Options that apply to all the event listeners that are bound by the renderer. */
61+
private _eventOptions = supportsPassiveEventListeners() ? ({passive: true} as any) : false;
62+
6163
/** Ripple config for all ripples created by events. */
6264
rippleConfig: RippleConfig = {};
6365

@@ -70,12 +72,12 @@ export class RippleRenderer {
7072
this._containerElement = elementRef.nativeElement;
7173

7274
// Specify events which need to be registered on the trigger.
73-
this._triggerEvents.set('mousedown', this.onMousedown.bind(this));
74-
this._triggerEvents.set('mouseup', this.onPointerUp.bind(this));
75-
this._triggerEvents.set('mouseleave', this.onPointerUp.bind(this));
75+
this._triggerEvents.set('mousedown', this.onMousedown);
76+
this._triggerEvents.set('mouseup', this.onPointerUp);
77+
this._triggerEvents.set('mouseleave', this.onPointerUp);
7678

77-
this._triggerEvents.set('touchstart', this.onTouchStart.bind(this));
78-
this._triggerEvents.set('touchend', this.onPointerUp.bind(this));
79+
this._triggerEvents.set('touchstart', this.onTouchStart);
80+
this._triggerEvents.set('touchend', this.onPointerUp);
7981

8082
// By default use the host element as trigger element.
8183
this.setTriggerElement(this._containerElement);
@@ -173,22 +175,23 @@ export class RippleRenderer {
173175
// Remove all previously register event listeners from the trigger element.
174176
if (this._triggerElement) {
175177
this._triggerEvents.forEach((fn, type) => {
176-
this._triggerElement!.removeEventListener(type, fn);
178+
this._triggerElement!.removeEventListener(type, fn, this._eventOptions);
177179
});
178180
}
179181

180182
if (element) {
181183
// If the element is not null, register all event listeners on the trigger element.
182184
this._ngZone.runOutsideAngular(() => {
183-
this._triggerEvents.forEach((fn, type) => element.addEventListener(type, fn));
185+
this._triggerEvents.forEach((fn, type) =>
186+
element.addEventListener(type, fn, this._eventOptions));
184187
});
185188
}
186189

187190
this._triggerElement = element;
188191
}
189192

190193
/** Function being called whenever the trigger is being pressed using mouse. */
191-
private onMousedown(event: MouseEvent) {
194+
private onMousedown = (event: MouseEvent) => {
192195
const isSyntheticEvent = this._lastTouchStartEvent &&
193196
Date.now() < this._lastTouchStartEvent + IGNORE_MOUSE_EVENTS_TIMEOUT;
194197

@@ -199,7 +202,7 @@ export class RippleRenderer {
199202
}
200203

201204
/** Function being called whenever the trigger is being pressed using touch. */
202-
private onTouchStart(event: TouchEvent) {
205+
private onTouchStart = (event: TouchEvent) => {
203206
if (!this.rippleDisabled) {
204207
// Some browsers fire mouse events after a `touchstart` event. Those synthetic mouse
205208
// events will launch a second ripple if we don't ignore mouse events for a specific
@@ -212,7 +215,7 @@ export class RippleRenderer {
212215
}
213216

214217
/** Function being called whenever the trigger is being released. */
215-
private onPointerUp() {
218+
private onPointerUp = () => {
216219
if (!this._isPointerDown) {
217220
return;
218221
}

0 commit comments

Comments
 (0)