避免长时间运行输入处理程序
1 .输入处理程序可能是应用出现性能问题的原因,因为他们可能阻止帧完成,并且可能导致额外的布局工作
2 .理想情况下,当用户在设备屏幕上触摸了页面的某个位置时,页面渲染层合并线程将接收到这个触摸事件并做出响应,比如移动页面元素。这个响应过程是不需要浏览器主线程参与的,也就是说不会导致js,布局,绘制过程的发生,不会导致卡顿
3 .但是如果对某个被触摸的元素绑定了输入事件处理函数,比如touchstart,touchmove,touchend,那么渲染层合并线程必须等待这些被绑定的处理函数执行完毕之后才能被执行。因为你可能在这些处理函数中调用了类似preventDefault的函数,这将会阻止输入事件touch.scroll等默认处理函数的运行。
4 .实际上,即使你没有在事件处理函数中调用preventDefault,渲染层合并线程也依然会等待,也就是用户的滚动页面操作被阻塞了,表现的行为就是滚动出现延迟或者卡顿
5 .基于这种机制,必须要保证对用户输入事件绑定的任何处理函数都能快速的执行,一定要节省出时间来渲染
6 .输入时间处理函数,比如scroll,touch事件的处理,都会在requestAnimationFrame之前调用执行。如果在上述输入事件的处理函数中做了修改样式属性的操作,那么这些操作都会被浏览器暂存起来,然后在调用requestAnimationFrame的时候操作,但是如果你在一开始做了读取样式的操作,那么将会立马触发浏览器的强制同步布局过程
7 .解决方法就是,对样式修改去抖动,控制其仅在下一次requestAnimationFrame中发生
8 .始终对除下一个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);