為提升 wheel
捲動/縮放效能,建議開發人員將 wheel
和 mousewheel
事件監聽器註冊為被動,方法是將 {passive: true}
選項傳遞至 addEventListener()
。將事件監聽器註冊為被動,可讓瀏覽器知道輪子監聽器不會呼叫 preventDefault()
,且瀏覽器可安全地執行捲動和縮放,而不會封鎖監聽器。
問題是,大多數情況下,輪盤事件的事件監聽器在概念上是被動的 (不會呼叫 preventDefault()
),但並未明確指定為此類事件,因此瀏覽器必須等待 JS 事件處理完成,才能開始捲動/縮放,即使不需要等待也一樣。在 Chrome 56 中,我們修正了 touchstart
和 touchmove
的這個問題,後來 Safari 和 Firefox 也採用了這項變更。如您在當時製作的示範影片所見,如果保留原始行為,捲動回應的延遲時間會明顯增加。在 Chrome 73 中,我們已將相同的介入措施套用至 wheel
和 mousewheel
事件。
介入
這項異動的目標是縮短使用者開始透過滑鼠滾輪或觸控板捲動後,更新螢幕畫面所需的時間,開發人員不必變更程式碼。我們的指標顯示,在根目標 (視窗、文件或主體) 上註冊的 wheel
和 mousewheel
事件事件監聽器中,有 75% 未指定任何值給被動選項,且超過 98% 的這類事件監聽器不會呼叫 preventDefault()
。在 Chrome 73 中,我們會將在根目錄目標 (視窗、文件或主體) 上註冊的 wheel
和 mousewheel
事件監聽器,預設為被動。這表示事件監聽器如下:
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()
,藉此覆寫預設行為,並將事件事件監聽器保留為阻斷事件。