移动端滚动穿透问题 ==> 移动端弹出fixed弹窗的话,在弹窗上滑动会导致下层的页面跟着滚动,这个叫“滚动穿透”
1.在弹出层的touchstart事件中调用preventDefault
这种方法不可取,至少有3个缺点:
1.如果弹出层本身是有滚动(条)的话,将会导致弹出层无法滚动,此时用这种方法无于饮鸩止渴。
2.一个很常见的场景,点击弹出层,弹出层消失掉,此时也无法触发弹出层的点击回调事。
3.弹出层内的任何事件都执行不了了。
2.弹出层touchmove + preventDefault
// 1.弹出层里不能有需要滚动的内容
// 2.如大段文字需要固定高度,显示滚动条也会被阻止
modal.addEventListener('touchmove', function(e) {
e.preventDefault();
}, false);
3.设置 html,body{overflow:hidden;}
在PC和移动端都能禁止掉下层的滚动。
4.最好的解决方案 ==> 在body元素上设置position: fixed
body.modal-open {
position: fixed;
width: 100%;
}
如果只是上面的 css,滚动条的位置同样会丢失,所以如果需要保持滚动条的位置需要用 js 保存滚动条位置关闭的时候还原滚动位置
var ModalHelper = (function(bodyCls) {
var scrollTop, doc, reg;
var bodyClassName = "";
var bodyEle = document.body;
return {
afterOpen: function() {
doc = document.documentElement.scrollTop ? document.documentElement : bodyEle;
scrollTop = doc.scrollTop;
if(bodyEle.classList){
bodyEle.classList.add(bodyCls)
}else{
bodyEle.className += " " + bodyCls;
}
bodyEle.style.top = -scrollTop + 'px';
bodyClassName = bodyEle.className;
},
beforeClose: function() {
if(bodyEle.classList){
bodyEle.classList.remove(bodyCls)
}else{
reg = new RegExp("\\b" + bodyCls + "\\b", "g", "gi");
if(reg.test(bodyClassName)){
bodyClassName = bodyClassName.replace(reg, "");
bodyEle.className = bodyClassName;
}
}
bodyEle.style.top = "";
doc.scrollTop = scrollTop;
}
};
})('modal-open');
5.延伸: document.scrollingElement ==> 新标准浏览器获取和设置 scrollTop
console.log(document.scrollingElement.scrollTop);
