输入处理程序可能是应用出现性能问题的原因,因为它们可能会阻止帧完成,并且可能导致额外(且不必要)的布局工作。
输入处理程序可能是应用出现性能问题的原因,因为它们可能会阻止帧完成,并且可能导致额外(且不必要)的布局工作。
摘要
- 避免长时间运行的输入处理程序;它们可能会阻止滚动。
- 不要在输入处理程序中进行样式更改。
- 使处理程序去除抖动;存储事件值并在下一个 requestAnimationFrame 回调中处理样式更改。
避免长时间运行的输入处理程序
在最快的情况下,当用户与页面交互时,页面的合成器线程可以获取用户的触控输入,只是移动内容。这不需要主线程执行任何工作,主线程执行 JavaScript、布局、样式或绘制操作。
![轻量级滚动;仅限合成器。](https://web.developers.google.cn/static/articles/debounce-your-input-handlers/image/lightweight-scrolling-co-d1e531e7414ca.jpg?authuser=5&hl=hr)
不过,如果您附加了输入处理程序(如 touchstart
、touchmove
或 touchend
),则合成器线程必须等待此处理程序执行完毕,因为您可以选择调用 preventDefault()
并阻止轻触滚动的发生。即使您没有调用 preventDefault()
,合成器也必须等待,因此用户的滚动操作会被阻止,这可能会导致卡顿和丢帧。
![大量滚动;合成器在 JavaScript 上被阻止。](https://web.developers.google.cn/static/articles/debounce-your-input-handlers/image/heavy-scrolling-composit-2d22d7b7e1daa.jpg?authuser=5&hl=hr)
简而言之,您应确保您运行的所有输入处理程序都能快速执行,并允许合成器执行其工作。
避免在输入处理程序中进行样式更改
输入处理程序(如滚动和轻触的处理程序)被安排在紧接任何 requestAnimationFrame
回调之前运行。
如果您在这些处理程序之一内进行了视觉更改,那么在 requestAnimationFrame
开始时,会有待处理的样式更改。如果您然后在 requestAnimationFrame 回调开始时读取视觉属性(如“避免大型、复杂的布局和布局抖动”中的建议所述),则会触发强制同步布局!
![大量滚动;合成器在 JavaScript 上被阻止。](https://web.developers.google.cn/static/articles/debounce-your-input-handlers/image/heavy-scrolling-composit-151ee35865c54.jpg?authuser=5&hl=hr)
使滚动处理程序去除抖动
上述两个问题的解决方法相同:您应始终对下一个 requestAnimationFrame
回调的视觉更改进行去抖动处理:
function onScroll (evt) {
// Store the scroll value for laterz.
lastScrollY = window.scrollY;
// Prevent multiple rAF callbacks.
if (scheduledAnimationFrame)
return;
scheduledAnimationFrame = true;
requestAnimationFrame(readAndUpdatePage);
}
window.addEventListener('scroll', onScroll);
这样做还有一个好处是让输入处理程序保持轻量级,这是非常棒的,因为现在您无需阻止滚动或触摸计算开销很大的代码等操作!