产品有三宝,弹窗,浮层加引导;
设计有三宝,透明,阴影加圆角;
运营有三宝,短信,推送加红包;
程序员有一宝,这个作不了。
随着移动端市场的份额越大,需求就越多样化。咱们今天讨论的是移动端的滚动穿透问题。上面这段调侃的话能够看出需求中弹窗浮层仍是挺常见的,那这个和滚动穿透有什么联系呢?css
我先解释下什么是滚动穿透:前端
页面滑出了一个弹窗,咱们用手指触摸屏幕滑动时,会发现弹窗下面的内容仍是在滚动。这个现象就是 滚动穿透。
接下就说下我对滚动穿透问题解决方案探索的过程,但愿对你们有点启发。git
需求: 但愿在点击图片的时候,从下方弹一个全屏的弹框来描述这张图片的详情。
接到这个需求以为没有难度,很快就提测了,而后就开始逛逛掘金。可刚看大佬们的文章看的开心的时候,测试就在微信我。心想来 bug 了?
忽然意识到写弹窗的时候忘记处理滚动穿透的问题了。记得第一次遇到这个问题的时候也是找了好久的资料。程序员
找到的第一个方法就是当弹窗触发的时候,给 overflow: scroll:
的元素加上一个 class
(通常都是 body
元素)。退出的时候去掉这个 class
。下面为了方便,会直接用 body
元素来代指弹窗下方的元素。github
// css 部分 modal_open { position: fixed; height: 100%; } // js 部分 document.body.classList.add('modal_open'); document.body.classList.remove('modal_open');
上面的这个方法能够解决滚动穿透问题,却也会带来新的问题。
即:bootstrap
body
的滚动位置会丢失,也就是body
的scrollTop
属性值会变为 0。
这个新问题比起滚动穿透自己来讲更加麻烦,因此这个方案是要进行优化的。segmentfault
既然添加 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'); // method modalSwitch: function(){ let self = this; if( self.switchFlag === 'close' ){ ModalHelper.afterOpen(); self.switchFlag = 'open'; }else{ ModalHelper.beforeClose(); self.switchFlag = 'close'; } }
方案二能够达到如下效果:微信
body
是固定的没法滚动;body
的滚动位置不会丢失;body
有 scroll 事件;方案二能够适应绝大多数的弹窗需求,提测后测试方也没有在提其余问题,这个问题算是完美的解决了。不过我在这个过程有一个疑问:网络
IOS 自有的橡皮筋效果会致使页面会出现短暂卡顿现象,暂时没有找到缘由,请教各位。
使用 preventDefault
阻止浏览器默认事件:
var modal = document.getElementById('modalBox'); modal.addEventListener('touchmove', function(e) { e.preventDefault(); }, false);
这个方案只适用于这个弹窗自己的高度小于屏幕的高度,即不可滚动的时候。touchmove
比 touchstart
更加合适。由于 touchstart
会连点击事件都阻止。
使用插件:
对于插件个人态度是,除非是本身实现起来太复杂,不然仍是本身花点时间去实现。缘由有二:
以上。
《前端词典》这个系列会持续更新,每一期我都会讲一个出现频率较高的知识点。但愿你们在阅读的过程中能够斧正文中出现不严谨或是错误的地方,本人将不胜感激;若经过本系列而有所得,本人亦将不胜欣喜。
内容: 前端以及网络相关知识点的介绍并加以实际应用做为辅助。
目的: 这个系列的文章能够对读者起到一点帮助,解开一些迷惑。
但愿各位多指点一二,不吝赐教。
【前端词典】继承 - JavaScript 必懂知识点