最近做了一个物体可拖拽的需求,由于drag-and-drop在手机上的支持性不是很好,就利用了touch系列事件,改变transform的translate进行位移,从而达到物体跟随手指移动的效果。

但是发现了有以下提示

[Violation] Added non-passive event listener to a scroll-blocking 'touchstart' event. 
Consider marking event handler as 'passive' to make the page more responsive.

虽然最终找到了原因是升级taro1.3版本(具体提issue给taro了),但是却让我陷入了思考。

可滑动节点应该是passive

相信大家在使用react开发的时候,如果在touch事件里添加e.preventDefault(),控制台会报以下的错误:

react-dom.development.js:1458 [Intervention] Unable to preventDefault inside passive event listener due to target being treated as passive

这是由于当监听touch事件时,react默认已经将addEventListener的第三个参数加上了passive:true,为了可滑动节点在滑动的时候不需要等待js执行的时候就进行滑动的动作,可以看以下touchmove受preventDefault的影响->传送门

从视频里可以看出来,当没有加passive: true时,页面滑动会延迟,甚至出现卡顿。

在可滑动节点上禁止touch的默认行为

因为react默认开启了passive,这让我们无法去通过js层面去禁止可滑动节点touch的默认行为,但是在一些场景下我们禁止掉滑动,通过自己的逻辑来实现“滑动效果”,这时候该怎么做呢?

这里还有一个法宝:
在css属性中,有那么一个东西叫做touch-action。
touch-action 用于设置触摸屏用户如何操纵元素的区域(例如,浏览器内置的缩放功能)。
当touch-action设置为none的时候,浏览器将不能对该节点进行任何的触摸行为,比如说双击图片放大这种行为也可以禁止。所以我们可以设置touch-action: none,代替preventDefault禁止滑动。


一画先生
83 声望12 粉丝

我司长期招聘前端开发工程师,有意的小伙伴+vx: Mr_yihua