PC端解決方案
pc端的解決思路就是在彈出遮罩層的時候取消已經存在的滾動條,達到無法滾動的效果。
也就是說給body添加overflow:hidden屬性即可,IE6、7下不會生效,需要給html增加overflow:hidden屬性。
要制作這個效果在PC端非常簡單,只需要設置html的高度為100%占滿屏幕,並且將html的overflow設置為hidden,即可保證頁面不可滾動。
但是同樣的問題在移動端情況就有所區別。僅僅設置html的上列屬性,在移動端仍然無法禁止頁面超出部分的滾動,我們需要設置下面的代碼才能在彈框出現的時候禁止頁面滾動:
html.style.overflow="hidden";
html.style.height="100%";
body.style.overflow="hidden";
body.style.height="100%";
原因是因為移動端是基於touch事件,要禁止基於touch事件的滾動,我們必須在對html禁止滾動的基礎之上,再將需要禁止滾動的內容上再增加一個包裹層塊級元素,然后將這個包裹層塊級元素高度設置為100%並設置overflow:hidden;,那么在這里我們認為body包裹了整個頁面,正是我們需要的塊級元素,將他也設置為禁止滾動,就可以保證移動端頁面的滑動時間不會觸發頁面滾動。
當用戶關閉了彈框,頁面也就恢復正常,我們設置如下CSS樣式屬性來還原整個頁面的滾動效果:
html.style.overflow="visible";
html.style.height="auto";
body.style.overflow="visible";
body.style.height="auto";
這些樣式正是對應CSS屬性的默認樣式。
然而這個方案有一個缺陷,就是ios系統下不兼容,黑幕的效果沒法阻止頁面的滾動。下面介紹移動端的另一種解決方案。
移動端解決方案
正是因為移動端的滾動基於屏幕的touch事件,因此誕生了方案二(手機淘寶就使用了這種方案)。
首先我們需要知道兩個前提知識點:1、重疊的兩個頁面元素,z-index值更高的會優先觸發事件監聽,從而可以在此控制是否讓事件流繼續;2、移動端滾動的touch事件,基於事件流。
有了上面兩個知識點的基礎,我們就可以來理解這種方案的設計思路。方案二的原理是:不對原頁面進行任何改動,僅僅只是用一個擁有更高z-index值的,布局為absolute或者fixed布局的黑幕(長寬100%)來擋住整個頁面,並且監聽黑幕的touchmove事件,在touchmove事件內結束事件流,從而阻擋事件流繼續。這樣,能夠產生滾動效果的touch事件就傳不到頁面上,也就不會發生滾動。
移動端取消滾動條是達不到效果的,這時就需要去除遮罩層和按鈕層的touchmove的默認事件,代碼如下:
mask.addEventListener("touchmove",function(e){
e.stopPropagation();
e.preventDefault();
},false);
后來我把e.stopPropagation()注釋了,沒有禁止事件冒泡,在遮罩彈出后touchmove以為頁面應該會滾動,但是頁面還是不滾動。然后我在頁面加了
document.getElementsByTagName(‘body’)[0].addEventListener("touchmove", function(){
alert(‘hello’);
})
;遮罩彈出后,手指touchmove滑動頁面不會滾動,但是會alert(‘hello’);,說明事件還是冒泡了,只是touchmove沒有傳到頁面上。猜測可能是這個原因,touchmove事件只針對第一次觸發的最上層的容器,而不會冒泡傳遞。