共计 985 个字符,预计需要花费 3 分钟才能阅读完成。
最近做了一个物体可拖拽的需求,由于 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 禁止滑动。