React禁止页面滚动踩坑实践与方案梳理

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了React禁止页面滚动踩坑实践与方案梳理相关的知识,希望对你有一定的参考价值。

参考技术A 最近在使用 React 技术栈重构一个单页应用,其中有个页面是实现城市选择功能,主要是根据城市的首字母来快速跳转到相应位置,比较类似原生 APP 中的电话联系人查找功能,页面如图

在上下滑动右侧 fixed 定位的元素时,页面会跟着一起滑动

当然这个现象在开发过程中应该会经常遇到,比如弹起 modal 框时,如果 modal框的内容高度小于框高度,滑动内容也会导致页面跟着滑动, 那么在 React 中像往常一样处理

使用 React 提供的事件绑定机制,分别绑定三个 handler ,在 onTouchMove 事件中,我希望通过 preventDefault 能够阻止父级元素的滚动

但实际的反馈却事与愿违,在调试中,我发现 Chrome 是有警告的,并且没有达到想要的效果

根据警告提示,找到的原因是

来源: https://www.chromestatus.com/features/5093566007214080

根据 chrome 的提示得知,是因为 Chrome 现在默认把通过在 document 上绑定的事件监听器 passive 属性(后面细说)默认置为 true,这样就会导致我设置的 e.preventDefault() 被忽视了。当然 Chrome 的这个做法是有道理,是为了提高页面滚动的性能,那么为了防止带来的副作用,官方考虑的很周到,给我们提供了一个 CSS 属性专门用来解决这个问题

https://developer.mozilla.org/zh-CN/docs/Web/CSS/touch-action

加上了这个属性,感觉世界总算和平了,But!在 ios 系统上测试发现,这个属性 x 用没有,查了下 Can I Use

确定无误,就是不支持,所以这个属性只在 Chrome 安卓等机型下是支持的,ios 这个就用不了,理想很丰满,显示很骨感。既然不兼容,那只能降级处理了,为了保证良好的功能体验,感觉是还要从 passive 上做处理,说到 passive 根据 MDN文档:addEventListener 的介绍,为了提高页面滚动性能,大多浏览器都默认把 touchstart 和 touchmove 在文档元素上直接注册的这个事件监听器属性设置成 passive:true ,而通过 AddEventListener 注册的事件依然没有变化

既然现在默认将事件 passive 的属性默认设置为 true ,那我就显式设置为 false 好了,查遍 React 的文档,也没发现事件监听器可以支持配置这个属性的,在 github 上发现这个帖子 Support Passive Event Listeners #6436 目前看依然是 open 状态的,现在不确定有没有支持这个属性

既然这样,只能单独对 touchmove 通过 AddEventListener 方法去注册事件监听了

加上这个方法后,this.sidebarTouchMove(e) 方法中的 e.preventDefault() 方法就可以正常使用了,而且没有警告提示,问题到此就算解决了

总结下,这里的坑主要是 chrome 和 safari 平台的标准不统一导致的,新的标准出台,其它宿主环境不能很好的支持,当然 react 官方对这个属性的支持也比较慢,同样的前端 UI 框架 Vue 就处理的很棒

不小心暴露了,我是个 Vue粉,233
ok,完 ~

原文地址: http://w3cay.com/post/dc49b55.html?title=React-scroll&from=jianshu

弹出层完美禁止页面滚动

页面中经常会遇到弹出层的部件,当弹出层激活时覆盖整个页面,且背景部分不能滚动。实现起来有以下要点:

  • 弹出层position设置为fixed,四个定位锚点均设为0;

  • 激活弹出层时给htmlbody设置overflow: hidden;

以下是实践:

codepen

为了让彻底禁止滚动,还可以在mousewheeltouchmove事件(分别对应PC和移动端)中调用preventDefault()方法:

function forbidScroll(e) {
    e.preventDefault && e.preventDefault();
    e.returnValue = false;
    e.stopPropagation && e.stopPropagation();
    return false;
}

需要注意的是:chrome默认将touchmove事件视为passive,目的是提高用户体验,让处理一般事件时页面一样可以滚动,所以addEventListener的第三个参数需设置为:

{
    passive:false
}

以面向对象的方式实现的结果:

codenpen

使用es6再次重构:

codenpen

原文:http://codepen.io/zhaojun/pos...

以上是关于React禁止页面滚动踩坑实践与方案梳理的主要内容,如果未能解决你的问题,请参考以下文章

蒙层禁止页面滚动的方案

禁止蒙层底部页面跟随滚动

移动端禁止弹窗蒙层下页面滚动

弹出层完美禁止页面滚动

uniapp禁止遮罩层下的页面滚动 终极解决办法

vue中禁止页面发生滚动