避免長(zhǎng)時(shí)間運(yùn)行輸入處理程序
1 .輸入處理程序可能是應(yīng)用出現(xiàn)性能問題的原因坦仍,因?yàn)樗麄兛赡茏柚箮瓿桑⑶铱赡軐?dǎo)致額外的布局工作
2 .理想情況下冤狡,當(dāng)用戶在設(shè)備屏幕上觸摸了頁(yè)面的某個(gè)位置時(shí),頁(yè)面渲染層合并線程將接收到這個(gè)觸摸事件并做出響應(yīng),比如移動(dòng)頁(yè)面元素泵喘。這個(gè)響應(yīng)過程是不需要瀏覽器主線程參與的,也就是說不會(huì)導(dǎo)致js般妙,布局纪铺,繪制過程的發(fā)生,不會(huì)導(dǎo)致卡頓
3 .但是如果對(duì)某個(gè)被觸摸的元素綁定了輸入事件處理函數(shù)碟渺,比如touchstart,touchmove,touchend鲜锚,那么渲染層合并線程必須等待這些被綁定的處理函數(shù)執(zhí)行完畢之后才能被執(zhí)行。因?yàn)槟憧赡茉谶@些處理函數(shù)中調(diào)用了類似preventDefault的函數(shù),這將會(huì)阻止輸入事件touch.scroll等默認(rèn)處理函數(shù)的運(yùn)行芜繁。
4 .實(shí)際上旺隙,即使你沒有在事件處理函數(shù)中調(diào)用preventDefault,渲染層合并線程也依然會(huì)等待浆洗,也就是用戶的滾動(dòng)頁(yè)面操作被阻塞了催束,表現(xiàn)的行為就是滾動(dòng)出現(xiàn)延遲或者卡頓
5 .基于這種機(jī)制,必須要保證對(duì)用戶輸入事件綁定的任何處理函數(shù)都能快速的執(zhí)行伏社,一定要節(jié)省出時(shí)間來渲染
6 .輸入時(shí)間處理函數(shù)抠刺,比如scroll,touch事件的處理,都會(huì)在requestAnimationFrame之前調(diào)用執(zhí)行摘昌。如果在上述輸入事件的處理函數(shù)中做了修改樣式屬性的操作速妖,那么這些操作都會(huì)被瀏覽器暫存起來,然后在調(diào)用requestAnimationFrame的時(shí)候操作聪黎,但是如果你在一開始做了讀取樣式的操作罕容,那么將會(huì)立馬觸發(fā)瀏覽器的強(qiáng)制同步布局過程
7 .解決方法就是,對(duì)樣式修改去抖動(dòng)稿饰,控制其僅在下一次requestAnimationFrame中發(fā)生
8 .始終對(duì)除下一個(gè)requestAnimationFrame回調(diào)的視覺更改
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);