React中禁止页面滚动
时间:2023-03-30 19:09:26
CSS
最近用react做了一个H5端的页面,主要实现了滑动选择弹出层的功能。效果如图:我遇到了一个问题。被屏蔽的页面也会滚动。这种现象在开发过程中经常遇到。一般的想法是使用event.preventDefault来防止父元素的滚动:{this.handleTouchMove}onTouchEnd={this.handleTouchEnd}onTouchCancel={this.handleTouchCancel}>{this.renderItems()}
滚动事件代码片段handleTouchMove=(event)=>{event.preventDefault();...};但是经过这波操作,我并没有如愿以偿。调试的时候,Chrome的alarm像冷雨一样打在我的脸上:根据warning关键字用google和baidu,等到如下结论:既然浏览器必须执行事件处理函数,那么它就可以知道是否preventDefault()已经被调用,导致浏览器没有及时响应滚动,有轻微的延迟。所以为了让页面滚动效果如丝般顺滑,从chrome56开始,在window、document、body上注册的touchstart和touchmove事件处理函数都会默认设置passive:true。浏览器忽略preventDefault()并且可以第一次滚动。经过仔细揣测,其实官方的考虑是有道理的,也是周到的。CSS中提供了一个属性touch-action,用于指定给定区域是否允许用户操作,以及如何响应用户操作。据此,我的解决方案是设置这个CSS属性:touch-action:none;我觉得一切都很顺利。我在手机上试了一下,用iPhone的Safari浏览器打开,还是不行。是的,90%都是浏览器兼容性问题。按预期检查CanIUse。所以如果是这种情况,剩下的解决办法就是在绑定事件的时候显式设置{passive:false}。查了React文档,发现可以支持配置这个属性的方法。在此由衷感叹不如Vue方便。如果是Vue,可以这样写:
这种情况下,只能绑定原生事件的文档。getElementById("picker").addEventListener('touchmove',this.handleTouchMove,{passive:false});终于,世界太平了。