預設讓滾輪快速捲動

Sahel Sharify
Sahel Sharify

為提升 wheel 捲動/縮放效能,建議開發人員將 wheelmousewheel 事件監聽器註冊為被動,方法是將 {passive: true} 選項傳遞至 addEventListener()。將事件監聽器註冊為被動,可讓瀏覽器知道輪子監聽器不會呼叫 preventDefault(),且瀏覽器可安全地執行捲動和縮放,而不會封鎖監聽器。

問題是,大多數情況下,輪盤事件的事件監聽器在概念上是被動的 (不會呼叫 preventDefault()),但並未明確指定為此類事件,因此瀏覽器必須等待 JS 事件處理完成,才能開始捲動/縮放,即使不需要等待也一樣。在 Chrome 56 中,我們修正了 touchstarttouchmove 的這個問題,後來 Safari 和 Firefox 也採用了這項變更。如您在當時製作的示範影片所見,如果保留原始行為,捲動回應的延遲時間會明顯增加。在 Chrome 73 中,我們已將相同的介入措施套用至 wheelmousewheel 事件。

介入

這項異動的目標是縮短使用者開始透過滑鼠滾輪或觸控板捲動後,更新螢幕畫面所需的時間,開發人員不必變更程式碼。我們的指標顯示,在根目標 (視窗、文件或主體) 上註冊的 wheelmousewheel 事件事件監聽器中,有 75% 未指定任何值給被動選項,且超過 98% 的這類事件監聽器不會呼叫 preventDefault()。在 Chrome 73 中,我們會將在根目錄目標 (視窗、文件或主體) 上註冊的 wheelmousewheel 事件監聽器,預設為被動。這表示事件監聽器如下:

window.addEventListener("wheel", func);

會變成:

window.addEventListener("wheel", func, {passive: true});

而如果在事件監聽器中呼叫 preventDefault(),系統會忽略該呼叫,並顯示以下開發人員工具警告:

[Intervention] Unable to preventDefault inside passive event listener due
to target being treated as passive. See https://www.chromestatus.com/features/6662647093133312

服務中斷和指南

在絕大多數情況下,不會發生破損情形。只有在少數情況下 (根據我們的指標,少於 0.3% 的網頁),由於 preventDefault() 呼叫在預設情況下會被視為被動,因此可能會發生非預期的捲動/縮放。應用程式可以透過 defaultPrevented 屬性,檢查呼叫 preventDefault() 是否有任何效果,進而判斷是否可能在實際情況中發生這種情況。針對受影響的案例,修正方式相對簡單:將 {passive: false} 傳遞至 addEventListener(),藉此覆寫預設行為,並將事件事件監聽器保留為阻斷事件。