今天在一个移动项目中遇到了一个问题,使用display: fixed设置了一个遮罩层,当上下滑动这个遮罩层到极限后后面的内容会跟着移动,开始以为是一个很简单的问题,没想到也是需要花点时间去试验各种方法。
在小程序中也是需要类似的解决方法。
阻止滚动条wheel事件
1 |
handleWheel (e) { |
1 |
<div class="wrap" @wheel="handleWheel"></div> |
该方法在浏览器上是没问题的不会继续滚动,但是再移动端上根本不起作用,因为移动端使用的是touchstart touchmove touchend,而且touch事件还有另外一个问题,因为click事件在这三个事件之后会等待300ms来判断是否会做出双击屏幕之后才会触发。
设置为overflow: hidden
弹出遮罩层之后不想让后面的内容滚动,可以尝试在弹出的时候设置滚动元素overflow: hidden禁止其滚动,同时给html,body均添加一个overflow:hidden的属性,取消的时候恢复滚动,但是还是有问题,禁用之后滚动位置会滚动到顶部。
解决这个滚动到顶部的方法是记录当前的scrollTop,取消的时候在赋值给当前页面的scroll
弹出层的touchmove事件中调用preventDefault
1 |
modal.addEventListener('touchmove', function(e) { |
这样用 js 阻止滚动后看起来效果不错了,但是也有一个缺点:
弹出层里不能有其它需要滚动的内容(如大段文字需要固定高度,显示滚动条也会被阻止)
完美解决方案
给不想让他滚动的内容使用如下css,使其不受滚动的影响同时也不需要控制其滚动事件,再控制其滚动位置达到完美解决的效果。
但是如果在vue中使用次方法,可能在路由变动的时候没有执行removclass导致body滚动效果有问题
1 |
.modal-open { |
1 |
const ModalHelper = (function (bodyCls) { |
参考
移动端滚动穿透问题
Modal scrolling on mobile devices - what is the current state
解决小程序的遮罩层滚动穿透