输入处理脚本可能会导致应用出现性能问题,因为它们可能会阻止帧完成,并导致额外的布局工作。
输入处理脚本可能会导致应用出现性能问题,因为它们可能会阻止帧完成,并导致额外的布局工作。
摘要
- 避免使用长时间运行的输入处理脚本;它们可能会阻止滚动。
- 请勿在输入处理脚本中进行样式更改。
- 对处理脚本进行防抖处理;存储事件值并在下一个 requestAnimationFrame 回调中处理样式更改。
避免使用长时间运行的输入处理脚本
在最快的情况下,当用户与页面互动时,页面的合成器线程可以获取用户的触摸输入并简单地移动内容。这不需要主线程执行任何工作,而 JavaScript、布局、样式或绘制都是在主线程中完成的。
但是,如果您附加了输入处理程序(例如 touchstart、touchmove 或 touchend),则合成器线程必须等待此处理程序执行完毕,因为您可能会选择调用 preventDefault() 并阻止触摸滚动发生。即使您不调用 preventDefault(),合成器也必须等待,因此用户的滚动会被阻止,这可能会导致卡顿和丢帧。
简而言之,您应确保运行的任何输入处理脚本都应快速执行,并允许合成器执行其工作。
避免在输入处理脚本中进行样式更改
输入处理脚本(例如滚动和触摸处理脚本)计划在任何 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);
这样做还有一个额外的好处,即可以使输入处理脚本保持轻量级,这非常棒,因为现在您不会在计算成本较高的代码中阻止滚动或触摸等操作!