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

方案一:

找到的第一个方法就是当弹窗触发的时候,给 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');

// 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 事件;

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


程序员阿宇
3.2k 声望791 粉丝

前端学习交流群:784783012 欢迎新手,进阶者