移動端開發時常常會碰到有全屏遮罩層的彈窗滾動穿透問題,網上大部分的解決方案是彈窗出現時給body絕對定位或者高度設置爲100%,並隱藏超出部分。html
可是這些解決方法,都存在這樣的問題:當頁面有滾動時,彈出彈窗,頁面會滾動至頂部。特別是當頁面有其餘根據document文檔滾動距離而絕對定位元素時,會致使頁面元素混亂。node
我通過查詢相關文檔和實踐,發現可經過監聽touchmove和touchstart事件,來達到背景不可滾動而彈出窗可滾動的目的。可看此demo,建議在移動設備上查看。git
下面詳細講解一下實現方法:github
當阻止了整個彈窗的touchmove默認事件後,背景將不再會滾動。bash
var node = document.querySelector('.forbid-scroll-wrap');
node.addEventListener('touchmove', function (e) {
e.preventDefault();
}, false);
複製代碼
可是這樣會致使彈窗內部也沒法滾動。因此須要判斷觸發touchmove事件的元素是否爲可滾動區域,代碼優化以下:優化
var node1 = document.querySelector('.can-scroll-wrap'),
node2 = document.querySelector('.forbid-scroll-wrap');
node2.addEventListener('touchmove', function (e) {
var target = e.target;
if ($(target).parents(canScrollWrap).length === 0 && $(target) != node1) {
e.preventDefault();
}
}, false);
複製代碼
以上只是解決了一個問題:滑動彈窗其餘地方背景頁面確實未跟隨滾動,可是沒去彈窗可滾動區域到底部或頂部後,再滑動,背景頁面仍可跟隨滾動。this
因此仍須要對可滾動區域的滑動事件作監聽:若向上滑動時,已到底部,或向下滑動時已到頂部,則阻止滑動事件。代碼以下:spa
node1.scrollTop = 0;
var offsetHeight = node1.offsetHeight,
scrollHeight = node1.scrollHeight;
node2.addEventListener('touchmove', function (e) {
var target = e.target;
if ($(target).parents(canScrollWrap).length === 0 && $(target) != node1) {
e.preventDefault();
}
}, false);
node1.addEventListener('touchmove', function (e) {
var changedTouches = e.changedTouches, canMove = false;
var scrollTop = this.scrollTop;
if (changedTouches.length > 0) {
var touch = changedTouches[0] || {};
var moveY = touch.clientY;
if (moveY > startY && scrollTop <= 0) {
canMove = false;
} else if (moveY < startY && scrollTop + offsetHeight >= scrollHeight) {
canMove = false;
}else{
canMove = true;
}
if (!canMove) {
e.preventDefault();
}
}
}, false);
node1.addEventListener('touchstart', function (e) {
var targetTouches = e.targetTouches || [];
if (targetTouches.length > 0) {
var touch = targetTouches[0] || {};
startY = touch.clientY;
}
}, false)
複製代碼
彈窗關閉後,可解除全部禁止code
node1.addEventListener('touchstart',null,false);
node1.addEventListener('touchmove',null,false);
node2.addEventListener('touchmove',null,false);
複製代碼
點此查看源碼htm