LiuL0703 / blog

https://liul0703.github.io
38 stars 11 forks source link

渲染性能分析(七)之Input Handlers #35

Closed LiuL0703 closed 4 years ago

LiuL0703 commented 5 years ago

对输入处理程序做防抖

处理用户输入也是潜在的可能会影响性能的因素,因为其可能会阻塞其他内容的加载并且导致不必要的布局(layout)工作

TL;DR

避免运行时间过长的处理程序

页面交互最快的情况是,当用户与页面交互时,页面的合成器线程接受用户的触摸输入并将内容四处移动。这个过程不需要与主线程通信,而是直接提交给GPU处理。所以不需要等待主线程对JS的处理、以及布局(layout)、绘制(paint)等操作完成。

Snipaste_2019-10-21_17-27-22-296a06f0-6a55-41a7-af01-ff773c8e1f7c

但是,如果附加了输入处理程序(如touchstart,touchmove,或者touchend)后,合成器线程必须等待该处理程序执行完毕,因为有可能调用了preventDefault()来阻止触摸滚动事件的发生。即使没有调用preventDefault(),合成器也必须等待其执行完毕,这样用户的滚动操作就被阻止就可能导致帧丢失从而引起卡顿。

Snipaste_2019-10-21_17-28-10-7182cacd-7819-4f15-8957-594510110f12

总而言之,你应该确保运行的所有输入处理程序都快速执行,并允许合成器执行其工作。

避免在输入处理程序中改变样式

输入处理程序被安排在requestAnimtionFrame回调之前运行。如果在这个处理程序中做样式上的修改,那么在requestAnimationFrame开始处有需要更改的样式处理,这会触发强制同步布局。

Snipaste_2019-10-21_17-41-01-f4a205b3-b672-4a2c-9ab0-e21e97d1d2d5

输入处理程序做防抖

上面两个问题的解决方案是相同的:你应该对下一个requestAnimationFrame的回调中做样式更改的情况做防抖处理。

function onScroll(evt){
    lastScrollY = window.scrollY;

    if(scheduleAnimationFrame)
        retun;
    scheduleAnimationFrame = true;
    requestAnimationFrame(readAndUpdatePage);
}

window.addEventListener('scroll',onScroll);

这样做还有一个好处,就是保持输入处理程序的轻量,因为这样就不会阻塞比如滚动等其他操作。