输入处理脚本可能会导致应用出现性能问题,因为它们可能会阻止帧完成,并导致额外且不必要的布局工作。
输入处理程序可能会导致应用出现性能问题,因为它们可能会阻止帧完成,并导致额外的不必要的布局工作。
摘要
- 避免使用长时间运行的输入处理程序;它们可能会阻止滚动。
- 请勿在输入处理程序中进行样式更改。
- 对处理程序进行去抖动处理;存储事件值,并在下一个 requestAnimationFrame 回调中处理样式更改。
避免长时间运行的输入处理程序
在最快的情况下,当用户与网页互动时,网页的 compositor 线程可以接收用户的触摸输入,然后只需移动内容即可。这不需要主线程执行任何工作,主线程负责执行 JavaScript、布局、样式或绘制操作。

不过,如果您附加了输入处理程序(例如 touchstart
、touchmove
或 touchend
),则 compositor 线程必须等待此处理程序完成执行,因为您可能会选择调用 preventDefault()
并停止触摸滚动。即使您不调用 preventDefault()
,合成器也必须等待,因此用户的滚动会被阻止,这可能会导致卡顿和丢帧。

简而言之,您应确保运行的所有输入处理脚本都应快速执行,并允许 compositor 执行其工作。
避免在输入处理脚本中更改样式
输入处理脚本(例如滚动和触摸处理脚本)会安排在任何 requestAnimationFrame
回调之前运行。
如果您在其中一个处理脚本中进行视觉更改,则在 requestAnimationFrame
开始时,系统会显示待处理的样式更改。如果您随后在 requestAnimationFrame 回调开始时读取视觉属性,则会触发强制同步布局,如“避免大型复杂布局和布局抖动”中的建议所述。

对滚动处理程序进行去抖动
上述两个问题的解决方法相同:您应始终对下一个 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);
这样做还有一个额外的好处,就是可以让输入处理程序保持轻量级,这非常棒,因为现在您不会因计算量大的代码而阻塞滚动或轻触等操作!