釋放輸入處理常式

輸入處理常式是應用程式效能問題的可能原因,因為這類處理常式可能會使影格無法完成,並造成額外及不必要的版面配置工作。

Paul Lewis

輸入處理常式可能會導致應用程式發生效能問題,因為這可能會使影格無法完成,並造成其他與不必要的版面配置工作。

摘要

  • 避免長時間執行的輸入處理常式,這些處理常式可能會封鎖捲動功能。
  • 請勿變更輸入處理常式的樣式。
  • 解放處理常式、儲存事件值,並處理下一個 requestAnimationFrame 回呼中的樣式變更。

避免長時間執行的輸入處理常式

在最快的情況下,當使用者與網頁互動時,網頁的轉換器執行緒可以接收使用者的觸控輸入內容,然後直接移動內容。這不需要透過主執行緒進行 JavaScript、版面配置、樣式或繪製作業。

輕巧捲動;僅限合成器。

不過,如果您附加輸入處理常式 (例如 touchstarttouchmovetouchend),則您可能會選擇呼叫 preventDefault() 並停止觸控捲動,因此,組合器執行緒必須等待這個處理常式執行完畢。即使您未呼叫 preventDefault(),合成器仍必須等候,且使用者的捲動會遭到封鎖,因此可能導致延遲和遺漏影格。

捲動速度緩慢;JavaScript 會封鎖合成器。

簡而言之,您應確保執行的所有輸入處理常式都能快速執行,並讓合成器執行其工作。

避免輸入處理常式中的樣式變更

輸入處理常式會安排在任何 requestAnimationFrame 回呼之前執行,例如捲動和觸控的處理常式。

如果在其中一個處理常式內進行視覺變更,則在 requestAnimationFrame 開始時,樣式變更會待處理的變更。如果您「接著」在 requestAnimationFrame 回呼的開頭讀取視覺屬性 (如「避免大型、複雜的版面配置和版面配置輾轉功能」中的建議),就會觸發強制同步版面配置!

捲動速度緩慢;JavaScript 會封鎖合成器。

減緩捲動處理常式

這兩個問題的解決方案相同:請一律將視覺變更分離到下一個 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);

這樣做還有另一個好處,就是可以讓輸入處理程序保持輕量化,這麼一來,您就不會在運算成本高的程式碼中阻斷捲動或觸控等操作!