mirror of
https://github.com/angular/angular.git
synced 2026-09-14 13:54:52 +08:00
perf(focus-monitor): use passive touch listener (#7957)
The `FocusMonitor` works by binding a `touchstart` (as well as some other events) listener to the `document` in order to keep track of focus. These changes make the `touchstart` listener `passive`, which means that on supported browsers it won't block rendering and should make scrolling smoother.
This commit is contained in:
committed by
Andrew Seguin
parent
816866738a
commit
ff7a13b053
@@ -80,7 +80,7 @@ describe('FocusMonitor', () => {
|
||||
|
||||
it('should detect focus via touch', fakeAsync(() => {
|
||||
// Simulate focus via touch.
|
||||
dispatchMouseEvent(buttonElement, 'touchstart');
|
||||
dispatchFakeEvent(buttonElement, 'touchstart');
|
||||
buttonElement.focus();
|
||||
fixture.detectChanges();
|
||||
tick(TOUCH_BUFFER_MS);
|
||||
@@ -262,7 +262,7 @@ describe('cdkMonitorFocus', () => {
|
||||
|
||||
it('should detect focus via touch', fakeAsync(() => {
|
||||
// Simulate focus via touch.
|
||||
dispatchMouseEvent(buttonElement, 'touchstart');
|
||||
dispatchFakeEvent(buttonElement, 'touchstart');
|
||||
buttonElement.focus();
|
||||
fixture.detectChanges();
|
||||
tick(TOUCH_BUFFER_MS);
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
* found in the LICENSE file at https://angular.io/license
|
||||
*/
|
||||
|
||||
import {Platform} from '@angular/cdk/platform';
|
||||
import {Platform, supportsPassiveEventListeners} from '@angular/cdk/platform';
|
||||
import {
|
||||
Directive,
|
||||
ElementRef,
|
||||
@@ -168,13 +168,16 @@ export class FocusMonitor {
|
||||
// When the touchstart event fires the focus event is not yet in the event queue. This means
|
||||
// we can't rely on the trick used above (setting timeout of 0ms). Instead we wait 650ms to
|
||||
// see if a focus happens.
|
||||
document.addEventListener('touchstart', (event: Event) => {
|
||||
document.addEventListener('touchstart', (event: TouchEvent) => {
|
||||
if (this._touchTimeout != null) {
|
||||
clearTimeout(this._touchTimeout);
|
||||
}
|
||||
this._lastTouchTarget = event.target;
|
||||
this._touchTimeout = setTimeout(() => this._lastTouchTarget = null, TOUCH_BUFFER_MS);
|
||||
}, true);
|
||||
|
||||
// Note that we need to cast the event options to `any`, because at the time of writing
|
||||
// (TypeScript 2.5), the built-in types don't support the `addEventListener` options param.
|
||||
}, supportsPassiveEventListeners() ? ({passive: true, capture: true} as any) : true);
|
||||
|
||||
// Make a note of when the window regains focus, so we can restore the origin info for the
|
||||
// focused element.
|
||||
|
||||
@@ -6,6 +6,27 @@
|
||||
* found in the LICENSE file at https://angular.io/license
|
||||
*/
|
||||
|
||||
/** Cached result of whether the user's browser supports passive event listeners. */
|
||||
let supportsPassiveEvents: boolean;
|
||||
|
||||
/**
|
||||
* Checks whether the user's browser supports passive event listeners.
|
||||
* See: https://github.com/WICG/EventListenerOptions/blob/gh-pages/explainer.md
|
||||
*/
|
||||
export function supportsPassiveEventListeners(): boolean {
|
||||
if (supportsPassiveEvents == null) {
|
||||
try {
|
||||
window.addEventListener('test', null!, Object.defineProperty({}, 'passive', {
|
||||
get: () => supportsPassiveEvents = true
|
||||
}));
|
||||
} finally {
|
||||
supportsPassiveEvents = supportsPassiveEvents || false;
|
||||
}
|
||||
}
|
||||
|
||||
return supportsPassiveEvents;
|
||||
}
|
||||
|
||||
/** Cached result Set of input types support by the current browser. */
|
||||
let supportedInputTypes: Set<string>;
|
||||
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
.demo-focusable {
|
||||
border: 2px solid transparent;
|
||||
}
|
||||
|
||||
.demo-focusable.cdk-focused {
|
||||
border: 2px solid red;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user