最近ios發佈新版本系統12.1,隨着部分用戶的系統更新,一些問題也漸漸暴露出來。。。ios
我當時就是一驚,通常出如今事件上的問題都是疑難雜症。況且是跟鍵盤相關的。瀏覽器
咱們都知道在H5端是無法監控鍵盤的彈出與收起的,resize事件觸發的機型極其有限,況且我在ios中實測沒有觸發,安卓反而能夠。由於安卓彈起鍵盤時會修改視窗的大小,可是ios並不會,若是你在ios上設置一個100%高度的body,彈起鍵盤後你會發現這個body是能夠上下滾動的,即100%高度的body超出了視窗。bash
(PS: iphoneX的測試機被拿走了,這是安卓下模擬的ios表現😭,總之ios能滾成這樣)
微信
下圖是一個問題描述,當咱們彈起鍵盤,而且使用以下的佈局時: app
body高度是100%,modal使用fixed定位,四個方向設置爲0,預期的結果應該是二者都適應窗口大小,彈起鍵盤時自動適應。安卓上與預期相同,ios打開後出現整個modal和body能夠滑動的狀況。iphone
ios上一直有個很🐂的優化,彈出鍵盤時會自動把當前輸入框滾動到可視區域,在安卓中會出現鍵盤遮擋輸入框的問題,須要手動調整,ios扳回一城👏👏。我在項目中爲了讓安卓達到一樣的效果也是死了很多腦細胞。佈局
可是!!項目自己在穩定運行半年的狀況下,此次開始出現問題了。。。測試
在ios 12.1 中,機型爲iphoneX,當咱們聚焦輸入框彈出虛擬鍵盤,而後點擊鍵盤收起。出現了以下的效果圖,而且下半部分作點擊事件無效。優化
從現象中找問題,在虛擬鍵盤被收起的狀況下,能夠看到modal框視圖正常得彈回了,可是仔細看看透明區域下,body視圖還處在鍵盤彈起時的狀態。what fuck? 而後modal下面的可操做區域始終點擊無效。。。。ui
推測是body沒有正確從新渲染,致使點擊事件不處於body內而沒法觸發。
(簡陋推測圖......)
那麼怎麼解決呢,是否是隻要把body‘推’會來就好了? 方向有了,如今是如何‘推’的問題。
上文有說過,ios下彈出/收起鍵盤是沒有觸發resize事件的,那麼在什麼節點觸發‘推’的操做就成了問題。
這時候封裝的好處就體現出來了,由於項目中全部的地方都是使用封裝過的input框,因此只須要在封裝中作改造就行了。ios中點擊虛擬鍵盤的完成按鈕會觸發失焦事件,安卓卻不會,正是咱們須要的鉤子。
在鉤子中設置「推回」:
onBlur = (e) => {
const { onBlur } = this.props;
document.body && (document.body.scrollTop = 0);
onBlur && onBlur(e);
}
複製代碼
問題初步解決,可是引起的新問題也很明顯,任何onBlur事件都會作出 scrollTop = 0 的操做,嚴重影響體驗。
繼續經過現象思考問題,當咱們使用滑動觸摸事件的時候,body會「跳動」到正常位置,而不不是正常的滾動,這一點很重要!
這代表了瀏覽器作了一個錯誤的渲染,那我不由想到,咱們作的「推」的操做是否必須?在一個錯誤的渲染下,咱們是否只須要在鍵盤收起後作一個觸發「重繪」的操做。
問題解決了,最終解決方案就很明顯:
onBlur = (e) => {
const { onBlur } = this.props;
document.body && (document.body.scrollTop = document.body.scrollTop);
onBlur && onBlur(e);
}
複製代碼
在input輸入框失去焦點的鉤子中設置滾動到原有位置(document.body.scrollTop = document.body.scrollTop)
,觸發瀏覽器的重繪,使的錯誤的渲染回覆正常,滾動位置也不會有改變,沒有影響體驗。
是否是很簡單?
解決方案的簡單,是創建在深層的思考中的,若是這篇文章能對你有所觸動,那個人寫做就沒有白費。
(絕望的是我出現bug時去搜索這個問題居然沒有找到可用答案😂😂)
/**
* 處理iOS 微信客戶端6.7.4 鍵盤收起頁面未下移bug
*/
;(/iphone|ipod|ipad/i.test(navigator.appVersion)) && document.addEventListener('blur', (e) => {
// 這裏加了個類型判斷,由於a等元素也會觸發blur事件
['input', 'textarea'].includes(e.target.localName) && document.body.scrollIntoView(false)
}, true)
複製代碼
— The End