解決移動端滾動穿透
之前一直做PC系統,目前做移動端也遇到一些問題,本文解決 移動端滾動 的糟心問題!
全域性滾動
全域性滾動即滾動是在 body上的滾動 。如果只有一個全域性滾動是沒有問題的,問題在於全域性滾動的頁面出現了 彈窗 如下圖所示情景:

在此情況下的彈窗會出現如下問題:
滾動穿透--固定彈窗
啥意思呢,就是在 彈窗 上 點選或滑動 的時候, 底層的全域性滾動也會跟著滑動 !!! 剛出現問題的時候也在網上查找了一波,嘗試瞭如下方法:
- 彈窗時給body設定overflow:hidden;(缺點:ios沒用)
- 彈窗時給body設定position:fixed;(缺點:滾動位置會丟失,ios沒用)
針對此情景的完美解決方法是:
給彈窗加上 @touchmove.stop.prevent
,即可阻止 touchmove
事件傳遞到 body
,也就解決了 滾動穿透 。
滾動穿透——滾動彈窗

還是這張圖,情況就是 彈窗裡也是有滾動的 !!!如果使用了 @touchmove.stop.prevent
,那的確可以解決滾動穿透的問題,但是由於阻止 了@touchmove
,自身也 無法滾動 了,不信自己寫demo試試~
那針對此種情況 完美解決 方案是: 在彈窗開啟的時候給body的全域性滾動設定 position:fixed
屬性,並 設定top值 ;由於設定了fixed屬性,那在彈窗的時候body就沒有滾動條了。此時如果這麼設定會發現body雖然沒有了滾動穿透,但是 原來的位置丟失 了。所以再給body設定fixed屬性的時候,要把 當前的滾動位置賦值給css的top屬性 ,那在 視覺上就沒有任何變化 了。
fixedBody () { let scrollTop = document.body.scrollTop || document.documentElement.scrollTop document.body.style.cssText += 'position:fixed;width:100%;top:-' + scrollTop + 'px;' } 複製程式碼
那在彈窗關閉的時候如何處理呢? 彈窗關閉的時候則要 清除fixed固定定位和top值 ;並 設定其滾動位置位置top值 ,則又恢復了滾動功能,而且視覺上沒有任何變化,是目前最完美的解決方案!
looseBody () { let body = document.body body.style.position = '' let top = body.style.top document.body.scrollTop = document.documentElement.scrollTop = -parseInt(top) body.style.top = '' } 複製程式碼
總結
以上兩種方案解決了固定彈窗和滾動彈窗對於body全域性滾動的影響。文章末尾在針對 vue做一個自定義指令封裝 。
區域性滾動
區域性滾動,還是剛才的圖片,在彈窗裡的滾動,在Android上滾動沒啥問題,但是在 ios區域性滾動 有時就會實現。
復現步驟:
- ①從滾動區域外從上往下化
- ②在滑動滾動區域,發現滾動竟然失效了!!!活見鬼了....這TM還是原生屬性。多重發幾次,一定可以復現的。
解決辦法: 使用外掛better-scroll,大傢伙自己研究文件就行。
vue封裝
vue:
directives: { fixed: { // inserted 被繫結元素插入父節點時呼叫 inserted () { let scrollTop = document.body.scrollTop || document.documentElement.scrollTop document.body.style.cssText += 'position:fixed;width:100%;top:-' + scrollTop + 'px;' }, // unbind 指令與元素解綁時呼叫 unbind () { let body = document.body body.style.position = '' let top = body.style.top document.body.scrollTop = document.documentElement.scrollTop = -parseInt(top) body.style.top = '' } } }, 複製程式碼
自定義指令使用 html:
<divv-if="isShowRecordModal" v-fixed> .... .... </div> 複製程式碼
該指令的 注意點 是必須使用 v-if
來 開啟關閉彈窗 ,因為該指令 依賴於dom的插入和登出 ,使用 v-show
是肯定不行的。