解决滚动警告: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相关小知识,撒一波花~

相关文章
相关标签/搜索