產品有三寶,彈窗,浮層加引導;
設計有三寶,透明,陰影加圓角;
運營有三寶,短信,推送加紅包;
程序員有一寶,這個作不了。
隨着移動端市場的份額越大,需求就越多樣化。咱們今天討論的是移動端的滾動穿透問題。上面這段調侃的話能夠看出需求中彈窗浮層仍是挺常見的,那這個和滾動穿透有什麼聯繫呢?css
我先解釋下什麼是滾動穿透:前端
頁面滑出了一個彈窗,咱們用手指觸摸屏幕滑動時,會發現彈窗下面的內容仍是在滾動。這個現象就是 滾動穿透。
接下就說下我對滾動穿透問題解決方案探索的過程,但願對你們有點啓發。git
需求: 但願在點擊圖片的時候,從下方彈一個全屏的彈框來描述這張圖片的詳情。
接到這個需求以爲沒有難度,很快就提測了,而後就開始逛逛掘金。可剛看大佬們的文章看的開心的時候,測試就在微信我。心想來 bug 了?
忽然意識到寫彈窗的時候忘記處理滾動穿透的問題了。記得第一次遇到這個問題的時候也是找了好久的資料。程序員
找到的第一個方法就是當彈窗觸發的時候,給 overflow: scroll:
的元素加上一個 class
(通常都是 body
元素)。退出的時候去掉這個 class
。下面爲了方便,會直接用 body
元素來代指彈窗下方的元素。github
// css 部分 modal_open { position: fixed; height: 100%; } // js 部分 document.body.classList.add('modal_open'); document.body.classList.remove('modal_open');
上面的這個方法能夠解決滾動穿透問題,卻也會帶來新的問題。
即:bootstrap
body
的滾動位置會丟失,也就是body
的scrollTop
屬性值會變爲 0。
這個新問題比起滾動穿透自己來講更加麻煩,因此這個方案是要進行優化的。segmentfault
既然添加 modal_open
這個 class
會使 body
的滾動位置會丟失,那麼咱們爲何不在滾動位置丟失以前先保存下來,等到退出彈窗的前在將這個保存下來的滾動位置在設置回去。而後就朝着這個方向開始 coding 。瀏覽器
// css 部分 .modal_open { position: fixed; height: 100%; } // js 部分 /** * ModalHelper helpers resolve the modal scrolling issue on mobile devices * https://github.com/twbs/bootstrap/issues/15852 */ 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'; } }
方案二能夠達到如下效果:微信
body
是固定的沒法滾動;body
的滾動位置不會丟失;body
有 scroll 事件;方案二能夠適應絕大多數的彈窗需求,提測後測試方也沒有在提其餘問題,這個問題算是完美的解決了。不過我在這個過程有一個疑問:網絡
IOS 自有的橡皮筋效果會致使頁面會出現短暫卡頓現象,暫時沒有找到緣由,請教各位。
使用 preventDefault
阻止瀏覽器默認事件:
var modal = document.getElementById('modalBox'); modal.addEventListener('touchmove', function(e) { e.preventDefault(); }, false);
這個方案只適用於這個彈窗自己的高度小於屏幕的高度,即不可滾動的時候。touchmove
比 touchstart
更加合適。由於 touchstart
會連點擊事件都阻止。
使用插件:
對於插件個人態度是,除非是本身實現起來太複雜,不然仍是本身花點時間去實現。緣由有二:
以上。
《前端詞典》這個系列會持續更新,每一期我都會講一個出現頻率較高的知識點。但願你們在閱讀的過程中能夠斧正文中出現不嚴謹或是錯誤的地方,本人將不勝感激;若經過本系列而有所得,本人亦將不勝欣喜。
內容: 前端以及網絡相關知識點的介紹並加以實際應用做爲輔助。
目的: 這個系列的文章能夠對讀者起到一點幫助,解開一些迷惑。
但願各位多指點一二,不吝賜教。
【前端詞典】繼承 - JavaScript 必懂知識點