滾動穿透問題的解決方案

滾動穿透問題體現在移動端彈出層滑動時,導致彈框下面頁面的滾動。

方案一:

使用 preventDefault 阻止瀏覽器默認事件:

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

該方案適用於彈框內容高度小於屏幕高度,即彈框內容不可滑動的場景。touchmove 比 touchstart 更加合適。因爲 touchstart 會連點擊事件都阻止。

 

方案二:

給 overflow: scroll;的元素加上一個 class (以 body 元素爲例)。退出的時候去掉這個 class

// css 部分
modal_open {
    position: fixed;
    height: 100%;
}

// js 部分
document.body.classList.add('modal_open');
document.body.classList.remove('modal_open');

該解決方案會帶來新的麻煩,如果原頁面不滾動的情況下,使用很完美,如果原頁面滾動到一定的位置,使用該方案後,關閉彈框原頁面會出現滾動位置丟失,即scrollTop 屬性值會變爲 0。需優化該方案爲方案三。

 

方案三:

對方案二進行優化,在彈框彈出時,對原頁面滾動位置進行保存,彈框關閉前,將原頁面滾動的位置設置回去。

// css 部分
.modal_open {
  position: fixed;
  height: 100%;
}

// js 部分
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';
    }
}

方案二達到的效果:

  1. 彈窗滾動的時候,下方的原頁面是固定的無法滾動;
  2. 頁面的滾動位置不會丟失;
  3. 頁面有 scroll 事件;

 

參考:

https://juejin.im/post/5c2dc9cce51d45690a254b79

developer.mozilla.org/en-US/docs/…

uedsky.com/2016-06/mob…

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章