釋放輸入處理常式

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

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

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