从新版浏览器报错看touch事件和touch-event属性

Unable to preventDefault inside passive event listener

浏览器报错:

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

根据浏览器报错给的链接,找到这篇文章,有了详细解释。Making touch scrolling fast by default

简而言之:

由于浏览器必须要在执行事件处理函数之后,才能知道有没有调用过 preventDefault() ,这就导致了浏览器不能及时响应滚动,略有延迟。

所以为了让页面滚动的效果如丝般顺滑,从 chrome56 开始,在 window、document 和 body 上注册的 touchstarttouchmove事件处理函数,会默认为是 passive: true。浏览器忽略 preventDefault() 就可以第一时间滚动了。
举例:

wnidow.addEventListener('touchmove', func) //效果和下面一句一样
wnidow.addEventListener('touchmove', func, {
      passive: true })

这就导致了一个问题:

如果在以上这 3个元素的 touchstarttouchmove 事件处理函数中调用 e.preventDefault() ,会被浏览器忽略掉,并不会阻止默认行为,且控制台会报出以上错误信息。

那么如何解决这个问题呢?不让控制台提示,而且preventDefault()有效果呢?
两个方案:
1、注册处理函数时,用如下方式,明确声明为不是被动的

window.addEventListener('touchmove', func, {
      passive: false })//不推荐,因为需要检测USER AGENT是否支持EventListenrOption.(https://github.com/WICG/EventListenerOptions)

2、应用 CSS 属性 touch-action

 touch-action: none;// 这样任何触摸事件都不会产生默认行为,但是 touch 事件照样触发。
 使得图片在处置方向也可以滑动和缩放。

根据谷歌的官方说法,谷歌不推荐在网页的touchstarttouchmove事件处理函数中调用preventDefault()但在移动端 safari 中仍需要),而是通过应用CSS属性touch-action阻止滚动和缩放,所以这一特性将来可能会应用到所有元素中。而touchend事件处理函数中可以调用preventDefault().

但实际情况可能并非如此。

关于touch-action

首先了解一下 touch-action 属性

CSS属性 touch-action 用于设置触摸屏用户如何操纵元素的区域(例如,浏览器内置的缩放功能)。

/* Keyword values */
touch-action: auto;//由浏览器处理触控事件
touch-action: none;//不进行任何操作

//启用单指水平平移手势。可以与 pan-y 、pan-up、pan-down 和/或 pinch-zoom 组合使用。
touch-action: pan-x;
//启用单指垂直方向水平平移。参考 pan-x
touch-action: pan-y;

//启用以指定方向滚动开始的单指手势。 一旦滚动开始,方向可能仍然相反。 请注意,滚动“向上”(pan-up)意味着用户正在将其手指向下拖动到屏幕表面上,同样 pan-left 表示用户将其手指向右拖动。 多个方向可以组合,除非有更简单的表示(例如,“pan-left pan-right”无效,因为“pan-x”更简单,而“pan-left pan-down”有效)。
touch-action: pan-left;
touch-action: pan-right;
touch-action: pan-up;
touch-action: pan-down;

//启用多手指平移和缩放页面。 这可以与任何平移值组合。
touch-action: pinch-zoom;

//浏览器只允许进行滚动和持续缩放操作。任何其它被auto值支持的行为不被支持。启用平移和缩小缩放手势,但禁用其他非标准手势,例如双击以进行缩放。 禁用双击可缩放功能可减少浏览器在用户点击屏幕时延迟生成点击事件的需要。 这是“pan-x pan-y pinch-zoom”(为了兼容性本身仍然有效)的别名。
touch-action: manipulation;

/* Global values */
touch-action: inherit;
touch-action: initial;
touch-action: unset;

更详细的touch-action说明请看 这里 。

需要注意避免的坑是 touch-action移动端的问题:
1.iOS 移动端不支持该属性。
2.在安卓手机中如果为了避免chrome报错而在全局设置touch-action:none属性,会禁止掉所有的触摸操作行为,导致页面不能滑动。

基于以上两个原因,即使谷歌官方推荐使用touch-action:none来处理这个报错,最终解决方案还是选择用js在注册事件处理函数时传入{passive:false}

window.addEventListener('touchmove', func, {
      passive: false })

最后,由于报错是由第三方库引发,修改第三方库的js源码过于繁琐,直接升级了第三方库解决了这个问题(此处应有表情)。

你可能感兴趣的:(js,前端,css)