背景

产品有三宝,弹窗,浮层加引导;设计有三宝,透明,阴影加圆角;运营有三宝,短信,推送加红包;程序员有一宝,这个做不了。

随着移动端市场的份额越大,需求就越多样化。我们今天讨论的是移动端的滚动穿透问题。上面这段调侃的话可以看出需求中弹窗浮层还是挺常见的,那这个和滚动穿透有什么联系呢?

我先解释下什么是滚动穿透:

页面滑出了一个弹窗,我们用手指触摸屏幕滑动时,会发现弹窗下面的内容还是在滚动。这个现象就是滚动穿透。

接下就说下我对滚动穿透问题解决方案探索的过程,希望对大家有点启发。

需求

需求: 希望在点击图片的时候,从下方弹一个全屏的弹框来描述这张图片的详情。

方案

接到这个需求觉得没有难度,很快就提测了,然后就开始逛逛掘金。可刚看大佬们的文章看的开心的时候,测试就在微信我。心想来 bug 了?

突然意识到写弹窗的时候忘记处理滚动穿透的问题了。记得第一次遇到这个问题的时候也是找了很久的资料。

方案一:

找到的第一个方法就是当弹窗触发的时候,给 overflow:scroll 的元素加上一个 class (一般都是 body元素)。退出的时候去掉这个 class。下面为了方便,会直接用 body 元素来代指弹窗下方的元素。

// css 部分modal_open {    position: fixed;    height: 100%;}// js 部分document.body.classList.add('modal_open');document.body.classList.remove('modal_open');

上面的这个方法可以解决滚动穿透问题,却也会带来新的问题。
即:

body 的滚动位置会丢失,也就是 body 的 scrollTop 属性值会变为 0。

这个新问题比起滚动穿透本身来说更加麻烦,所以这个方案是要进行优化的。

方案二:

既然添加 modal_open 这个 class 会使 body 的滚动位置会丢失,那么我们为什么不在滚动位置丢失之前先保存下来,等到退出弹窗的前在將这个保存下来的滚动位置在设置回去。然后就朝着这个方向开始 coding 。

// css 部分.modal_open {  position: fixed;  height: 100%;}// js 部分/** * ModalHelper helpers resolve the modal scrolling issue on mobile devices * https://github.com/twbs/bootstrap/issues/15852 */var ModalHelper = (function(bodyClass) {    var scrollTop;    return {        afterOpen: function() {            scrollTop = document.scrollingElement.scrollTop  ||                        document.documentElement.scrollTop ||                         document.body.scrollTop;            document.body.classList.add(bodyClass);            document.body.style.top = -scrollTop + 'px';        },        beforeClose: function() {            document.body.classList.remove(bodyClass);            document.scrollingElement.scrollTop = document.documentElement.scrollTop = document.body.scrollTop = scrollTop;        }    };})('modal_open');// methodmodalSwitch: function(){    let self = this;    if( self.switchFlag === 'close' ){        ModalHelper.afterOpen();        self.switchFlag = 'open';    }else{        ModalHelper.beforeClose();        self.switchFlag = 'close';    }}

方案二可以达到以下效果:

  1. 弹窗滚动的时候,下方的 body 是固定的无法滚动;

  2. body 的滚动位置不会丢失;

  3. body 有 scroll 事件;

方案二可以适应绝大多数的弹窗需求,提测后测试方也没有在提其他问题,这个问题算是完美的解决了。不过我在这个过程有一个疑问:

IOS 自有的橡皮筋效果会导致页面会出现短暂卡顿现象,暂时没有找到原因,请教各位。

方案三:

使用 preventDefault 阻止浏览器默认事件:

var modal = document.getElementById('modalBox');modal.addEventListener('touchmove', function(e) {    e.preventDefault();}, false);

这个方案只适用于这个弹窗本身的高度小于屏幕的高度,即不可滚动的时候。touchmove 比 touchstart更加合适。因为 touchstart 会连点击事件都阻止。

其他方案:

使用插件:

对于插件我的态度是,除非是自己实现起来太复杂,否则还是自己花点时间去实现。原因有二:

  1. 使用插件就意味着需要引入的文件至少多了一个。

  2. 插件过多,担心日后项目升级维护成本加大。

当然我也不反对,因为很多插件都自己处理了这个问题;无需我们再费时间去处理。

以上。

最后

如果你想进【大前端交流群】关注公众号点击“交流加群”添加机器人自动拉你入群。关注我第一时间接收最新干货。

©著作权归作者所有:来自51CTO博客作者mb5ff592736e0cf的原创作品,如需转载,请注明出处,否则将追究法律责任

更多相关文章

  1. 介绍一种更方便的代理池实现方案
  2. Python 中更优雅的环境变量设置方案
  3. Python 中更优雅的日志记录方案
  4. 抄答案就是了,两套详细的设计方案,解决头疼的掉单问题
  5. 聊聊对账系统的设计方案
  6. 超级好用的RabbitMQ 消息 100% 投递的解决方案!
  7. 性能优化 | 实战中几点性能优化方案!
  8. 全息金融行业数据安全解决方案
  9. 关于新版Anaconda(v5.1.0)安装后可能出现的跟 nodejs 错误相关问题

随机推荐

  1. Android ConstraintLayout 约束布局详解
  2. Android(安卓)触摸事件大全
  3. Android 存储路径浅析
  4. Android模擬器adb命令介紹
  5. Android带多选功能的PhotoPicker
  6. 解决Android SDK Manager下载问题和andro
  7. android 电池(二):android关机充电流程、充
  8. [九鼎RK3399Pro] Android(安卓)8.1默认自
  9. android单位转换(TypedValue)
  10. android文件系统挂载分析(1)---正常开机