釋放輸入處理常式

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

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

這麼做還有另一個好處,就是讓輸入處理常式保持輕微的好處,因為現在就不會封鎖捲動或使用運算成本高昂的程式碼等項目!