當頁面出現浮層的時候,滑動浮層的內容,正常狀況下預期應該是浮層下邊的內容不會滾動;然而事實並不是如此。 css
先去github上搜索一番,發現有解決此問題的開源包,簡單粗暴直接挑選了其中star的最高的(body-scroll-lock)操做一番! 使用後發現有一些問題:html
查源碼發現該包在iOS
端使用禁止touchmove
的方式單獨處理,可是在其餘端只是給body
加overflow: hidden
簡單處理。 因而決定寫一個針對多端通用的包來處理相似的問題。android
看到下邊的滾動確定馬上就想到了是整個viewport
的滾動,那麼若是給body設置overflow: hidden
,此時body的內容就只有一屏了,確定不會滾動了;ios
body { overflow: hidden; } 複製代碼
此方案在pc端完美解決了咱們的問題,然而事情並無那麼簡單;git
再試試移動端: github
上邊想到給body設置overflow: hidden
在移動端並不能解決咱們的問題,是否在於body的height沒有設置web
100%
;同時使用這兩個操做彷佛完美知足了咱們的需求; chrome
top值
不就定位到咱們想要的位置了(聰明如我)。
tips: body 設置
relative
定位會頁面自身拉上去,下邊留白npm
屢次實驗發現這個方案在android
端中完美達到了咱們想要的結果,可是在ios
端並不理想;每次定位的時候會有閃動的問題;好事多磨,接着探索ios端的方案。瀏覽器
若是禁止掉頁面的touchmove
是否可行呢?話很少說就是幹! 當彈出浮層的時候禁掉頁面元素的touchmove
document.addEventListener('touchmove', function (event) { event.preventDefault() }) 複製代碼
測試發現沒有達到想象中的效果,感受這個結果並不能接受啊,禁止document
的touchmove
都不能禁止滾動的嗎?
進一步的探索後發現緣由竟是這個屬性
原來是瀏覽器作的一些優化,chrome passive-event-listeners Passive Event Listeners是Chrome提出的一個新的瀏覽器特性:Web開發者經過一個新的屬性passive
來告訴瀏覽器,當前頁面內註冊的事件監聽器內部是否會調用preventDefault
函數來阻止事件的默認行爲,以便瀏覽器根據這個信息更好地作出決策來優化頁面性能。當屬性passive
的值爲true的時候,表明該監聽器內部不會調用preventDefault
函數來阻止默認滑動行爲,Chrome瀏覽器稱這類型的監聽器爲被動(passive)監聽器。
知道問題就好說了,給addEventListener
傳入第三個參數
document.addEventListener('touchmove', function (event) { event.preventDefault() }, { passive: false }) 複製代碼
大功告成! 忽然想到,若是浮層中還須要滾動那就不GG了! so,是否是能夠有選擇性的禁止滾動(在浮層中元素滾動到最頂部或者最底部以後禁止滾動)。 單獨處理浮層中須要滾動的元素;
targetElement.ontouchmove = function (event) { const clientY = event.targetTouches[0].clientY - initialClientY if (targetElement && targetElement.scrollTop === 0 && clientY > 0) { return preventDefault(event) } if (targetElement && (targetElement.scrollHeight - 1 - targetElement.scrollTop <= targetElement.clientHeight) && clientY < 0) { return preventDefault(event) } event.stopPropagation() return true } 複製代碼
這個方案在ios
中完美實現,可是在 android
中仍是有一點問題;浮層內容拉到最頂部或者最底部的時候依然會帶動頁面的內容有必定程度的移動。
終極方案來啦!
tua-body-scroll-lock便是在ios
、android
和PC
各個端單獨處理,保證在每一個端均可以實現完美的效果!
$ npm i -S tua-body-scroll-lock # OR $ yarn add tua-body-scroll-lock 複製代碼
import { lock, unlock } from 'tua-body-scroll-lock' // 禁止滑動後還須要內部能夠滾動的元素(針對移動端ios處理) const targetElement = document.querySelector("#someElementId"); lock(targetElement) unlock(targetElement) 複製代碼
tips: PC端不須要targetElement, 不傳targetElement也不想要控制檯提示能夠傳
null
import { lock, unlock } from 'tua-body-scroll-lock' lock() unlock() 複製代碼