釋放輸入處理常式

輸入處理常式可能會導致應用程式效能問題,因為這類處理常式可能會阻止影格完成,並且可能造成額外或不必要的版面配置工作。

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);

這種做法還有一個好處,那就是保持輸入處理常式的輕度,這真是太棒了,因為您無需封鎖捲動或輕觸運算成本高昂的程式碼!