起因
近期更新專案,使用fullpage.js
實現單頁滾動,頁面報錯:
passive event listener
關於 passive event listener
的問題已遇到過多次。
當我們滾動頁面的時候或者需要監聽 touch
事件的時候,瀏覽器無法預先知道一個事件處理函式中會不會呼叫 preventDefault()
,故而通過一個延遲,大約300ms的停頓來檢測,整個頁面就顯得卡頓。
為了優化這一點,自chrome51開始,passive event listener
被引入。
通過對 addEventListener
第三個引數設定 { passive : true }
來避免瀏覽器檢查是否在touch
事件handler
中呼叫了preventDefault
。
這種情形下,如果我們依舊呼叫preventDefault
,就會在控制檯列印一個警告,告訴我們passive event listener
中的preventDefault
會被忽略。
通常解決的方法有兩個:
-
addEventlistener
第三個引數傳入{ passive : false }
document.addEventListener( 'touchstart', function(event){ event.preventDafault(); }, { passive: false } ); 複製程式碼
-
觸發全域性的
css
樣式touch-action
,例如* { touch-action: pan-y; } //表示手指頭可以垂直移動 複製程式碼
touch-action
由於是第三方的外掛,選擇了全域性css樣式的覆蓋。
在 Chrome(版本 55 及更高版本)、Internet Explorer 和 Edge 中,
PointerEvents
是建議的自定義手勢實現方法。
PointerEvents
的一大特色是,它將包括滑鼠、觸控和觸控筆事件在內的多種輸入型別合併成一個回撥集。需要偵聽的事件是pointerdown
、pointermove
、pointerup
和pointercancel
。其他瀏覽器中的對應項是
touchstart
、touchmove
、touchend
和touchcancel
觸控事件,如果想為滑鼠輸入實現相同的手勢,則需實現mousedown
、mousemove
和mouseup
。使用這些事件需要對 DOM 元素呼叫
addEventListener()
方法,使用的引數為事件名稱、回撥函式和一個布林值。布林值決定是否應在其他元素有機會捕獲並解釋事件之前或之後捕獲事件。(true
表示想要先於其他元素捕獲事件)
// Check if pointer events are supported. if (window.PointerEvent) { // Add Pointer Event Listener swipeFrontElement.addEventListener('pointerdown', this.handleGestureStart, true); swipeFrontElement.addEventListener('pointermove', this.handleGestureMove, true); swipeFrontElement.addEventListener('pointerup', this.handleGestureEnd, true); swipeFrontElement.addEventListener('pointercancel', this.handleGestureEnd, true); } else { // Add Touch Listener swipeFrontElement.addEventListener('touchstart', this.handleGestureStart, true); swipeFrontElement.addEventListener('touchmove', this.handleGestureMove, true); swipeFrontElement.addEventListener('touchend', this.handleGestureEnd, true); swipeFrontElement.addEventListener('touchcancel', this.handleGestureEnd, true); // Add Mouse Listener swipeFrontElement.addEventListener('mousedown', this.handleGestureStart, true); } 複製程式碼
touch-action
支援的關鍵字有:
touch-action: auto;
touch-action: none;
touch-action: pan-x;
touch-action: pan-left;
touch-action: pan-right;
touch-action: pan-y;
touch-action: pan-up;
touch-action: pan-down;
touch-action: pinch-zoom;
touch-action: manipulation;
複製程式碼
結束語
Unable to preventDefault inside passive event listener
這個問題出現有一段時間,沒想到可以通過touch-action相關css屬性去解決,邂逅touch-action相關小知識,撒一波花~