IOS 瀏覽器軟鍵盤的拉起與收縮、微信 IOS 瀏覽器底部導航條的顯示與隱藏,很容易致使頁面佈局錯位(相對窗體的絕對定位元素):git
window
對象的 resize
事件,而 IOS 不會window
對象的 resize
事件,而 Android 中沒有底部導航條window
對象的 resize
事件無論是 IOS 瀏覽器軟鍵盤的拉起與收縮,仍是微信 IOS 瀏覽器底部導航條的顯示與隱藏,都是改變的 window 窗體的大小。github
微信 IOS 瀏覽器底部導航條的顯示與隱藏跟軟鍵盤的拉起與收縮是差很少的,但微信 IOS 瀏覽器底部導航條還有一個很大的特色:瀏覽器
在單頁面應用(SPA)中,當路由發生變化時,底部導航條會一會兒就顯示,而這很難肯定是先渲染了頁面仍是先顯示了底部導航條,
這也很容易致使元素佈局錯位。微信
新建 watch-keyboard.js
腳本,引入到頁面中。函數
當頁面中鍵盤彈起時,body
會有 keyboard-active
class,能夠根據這個隱藏一些元素。佈局
import {isIos} from '../utils'; import debounce from 'lodash/debounce'; // 初始高度 const winHeight = window.innerHeight; // 判斷是否是彈起了軟鍵盤 const judgeDistance = 200; if (!isIos) { window.addEventListener( 'resize', debounce(() => { if (window.innerHeight < winHeight - judgeDistance) { // 鍵盤彈起 document.body.classList.add('keyboard-active'); } else { document.body.classList.remove('keyboard-active'); } }, 300), !1 ); } else { // IOS 軟鍵盤的彈起與收縮不會觸發 `window` 對象的 `resize` 事件,用定時器實現 // 保證可以滾動 document.body.style.minHeight = (winHeight + 2) + 'px'; // 上兩次高度記錄 let secondLastWinHeight = winHeight; // 上一次高度記錄 let lastWinHeight = winHeight; setInterval(() => { const newWinHeight = window.innerHeight; // 變化結束 if (secondLastWinHeight !== lastWinHeight && lastWinHeight === newWinHeight) { if (newWinHeight < winHeight - judgeDistance) { // 鍵盤彈起 document.body.classList.add('keyboard-active'); } else { document.body.classList.remove('keyboard-active'); // window 須要滾動一下,讓頁面刷新一下,不然彈框會出現錯位的問題 window.scrollTo(0, window.scrollY ? window.scrollY - 1 : 1); } } secondLastWinHeight = lastWinHeight; lastWinHeight = newWinHeight; }, 300); // 能夠根據須要調整間隔時間(越小越精確) }
當軟鍵盤彈起時,又點擊了一個按鈕,而後顯示彈框(如:從底部向上彈出)的時候,這個時候就須要等待軟鍵盤收起以後,IOS 刷新屏幕以後,再顯示彈框。code
新建 wait-for-stable-win-height.js
腳本,引入到頁面中。對象
import { isIos } from '../utils'; /** * 等待 window 高度不變了以後執行一個回調函數 * * @param onComplete 完成的回調 * @param delay 延遲多少時間再判斷 * @param interval 定時器間隔時間 */ export default ({ onComplete, delay = 200, interval = 50 }) => { setTimeout(() => { let winHeight = window.innerHeight; const timer = setInterval(() => { const newWinHeight = window.innerHeight; if (winHeight === newWinHeight) { clearInterval(timer); if (onComplete) { if (!isIos) { setTimeout(() => { onComplete(); }, 100); return; } // window 須要滾動一下,讓頁面刷新一下,不然彈框會出現錯位的問題 window.scrollTo(0, window.scrollY ? window.scrollY - 1 : 1); setTimeout(() => { onComplete(); }, 200); } } else { winHeight = newWinHeight; } }, interval); }, delay); };
更多博客,查看 https://github.com/senntyou/blogsblog
做者:深予之 (@senntyou)事件
版權聲明:自由轉載-非商用-非衍生-保持署名(創意共享 3.0 許可證)