解決滾動警告:Unable to preventDefault inside passive event listener

原由

近期更新項目,使用fullpage.js實現單頁滾動,頁面報錯: css

passive event listener

關於 passive event listener 的問題已遇到過屢次。chrome

當咱們滾動頁面的時候或者須要監聽 touch 事件的時候,瀏覽器沒法預先知道一個事件處理函數中會不會調用 preventDefault(),故而經過一個延遲,大約300ms的停頓來檢測,整個頁面就顯得卡頓。瀏覽器

爲了優化這一點,自chrome51開始,passive event listener被引入。ide

經過對 addEventListener第三個參數設置 { passive : true } 來避免瀏覽器檢查是否在touch事件handler中調用了preventDefault函數

這種情形下,若是咱們依舊調用preventDefault,就會在控制檯打印一個警告,告訴咱們passive event listener 中的preventDefault會被忽略。優化

一般解決的方法有兩個:ui

  • addEventlistener第三個參數傳入{ passive : false }this

    document.addEventListener(
      'touchstart',
      function(event){
        event.preventDafault();
      },
      { passive: false }
    );
    複製代碼
  • 觸發全局的css樣式touch-action,例如spa

    * { touch-action: pan-y; } 
    //表示手指頭能夠垂直移動
    複製代碼

touch-action

因爲是第三方的插件,選擇了全局css樣式的覆蓋。插件

在 Chrome(版本 55 及更高版本)、Internet Explorer 和 Edge 中,PointerEvents 是建議的自定義手勢實現方法。

PointerEvents 的一大特點是,它將包括鼠標、觸摸和觸控筆事件在內的多種輸入類型合併成一個回調集。須要偵聽的事件是 pointerdownpointermovepointeruppointercancel

其餘瀏覽器中的對應項是 touchstarttouchmovetouchendtouchcancel 觸摸事件,若是想爲鼠標輸入實現相同的手勢,則需實現 mousedownmousemovemouseup

使用這些事件須要對 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相關小知識,撒一波花~

相關文章
相關標籤/搜索