滾動穿透問題體現在移動端彈出層滑動時,導致彈框下面頁面的滾動。
方案一:
使用 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';
}
}
方案二達到的效果:
- 彈窗滾動的時候,下方的原
頁面
是固定的無法滾動; - 原
頁面
的滾動位置不會丟失; - 原
頁面
有 scroll 事件;
參考:
https://juejin.im/post/5c2dc9cce51d45690a254b79