前言:這裏移動端主要指 hybrid app 中的H5頁面。app 中對頁面 樣式和功能 的需求會更精細一點。css
一、適配: 手機端的尺寸多樣,3.5英寸的 iPhone4應該是最小的,只要考慮 兼容到iPhone4 就能夠了。(iPhone4的用戶量如今也不多,有時只要 兼容到iPhone5 就能夠了)html
哪怕有比這個尺寸小的,都不是多人使用的。多是個位數,甚至是沒有。爲數很少的幾款這樣的手機處理能力也很低下。 https://digi.tech.qq.com/a/20150312/011872.htm#p=1vue
iPhone4 使用狀況:iPhone4的系統, 如今的不少軟件都運行不了。 https://www.pc841.com/shouji/iPhone/19249.html(系統升級後也會有問題,大部分用戶是不會去升級的) 或 https://t.cj.sina.com.cn/articles/view/2972527830/b12d2cd60010084gl
android
總結:ios
rem + 媒體查詢 適配(rem基本能夠適配大部分的移動端的適配,解決不了的使用媒體查詢基本能夠解決),重點熟練下媒體查詢手機是用height仍是device-height來查詢的。有的手機,下面有一條黑色的手機按鍵,此時的device-height有沒有包含這塊高度。
注:不一樣手機寬度基本沒什麼適配的,rem基本就解決了。主要是針對須要一屏顯示的頁面,高度差距太大,用rem基本沒什麼效果。web
二、 JS 呼起和隱藏鍵盤(默認是須要用戶點擊輸入框才能呼起): 智能機的鍵盤都是軟鍵盤。應用中有呼起鍵盤和隱藏鍵盤的需求。segmentfault
呼起鍵盤:進入搜索頁,要求鍵盤拉起。主要聚焦到input框就能夠。(安卓上沒有問題,ios上無效)瀏覽器
this.$refs.input.focus() // 在一個demo上安卓 和 ios都有效,可是正式項目中,ios中無效
隱藏鍵盤:經過給input標籤,設置 readonly 屬性就可使鍵盤收起來了。(安卓上沒有問題,ios上無效)緩存
<input type="text" ref="input" :readonly="readonly">
或,下面的方法 安卓 和 ios上都有效微信
this.$refs.input.blur()
三、軟鍵盤呼起 引發的兼容性問題:
a、 會使webview高度變小(這裏就要求body最好設置一個最小的高度爲沒有鍵盤時的高度),而且 fixed定位元素 跟着鍵盤上移 (安卓的問題):
問題緣由:
安卓手機:同一個手機,H5頁面的 視口高度在鍵盤拉起和隱藏時,不同的。拉起時,鍵盤部分的高度變成原生的內容了,H5容器高度就變小了。(H5頁面自己的高度是不變的)
通常狀況這個都不影響,可是若是底部有fixed定位的話。鍵盤拉起時,會把這塊內容也移上去的,須要作一個判斷進行隱藏(這個隱藏必須是針對對安卓機,ios機上不能隱藏。ios上也隱藏了,鍵盤)。
ios手機:更不正常,鍵盤彈出不影響H5容器的大小變化的,即clientHeight的大小不變,可是卻出現了滾動(若是clientHeight同步變小,能夠理解爲變成了一個小屏的容器。可是ios這樣,只是把滾動條的範圍變小了;
滾動條到底了,頁面的底部在鍵盤的上了。鍵盤遮擋的部分也是屬於clientHeight,這一部分的高度,憑空給H5頁面了)。總結起來就,ios中鍵盤彈起,會給H5頁面的高度增長了一個鍵盤的高度。
參考哪些高度發生的變化 https://blog.csdn.net/weixin_34163553/article/details/88686238
我的見解:鍵盤彈出,能夠這樣理解爲h5的底板的大小就是webview的大小,包括鍵盤。底板上一張畫布,畫布高度能夠被撐高,html、body等元素是固定在畫布上的。瀏覽器中頁面的滾動的跟着畫布滾動的。
安卓上,畫布的最小高度是底板不包括鍵盤的高度; ios上,畫布的最小高度是低板的高度加上鍵盤的高度。(css無非操做畫布的屬性)
解決問題:
頁面只能是一屏的:這個要考慮自適應。鍵盤呼起,webview的高度變小了。使用 absolute 定位,bottom 設置,定位參考的元素高度不能受webview高度的影響(給body設置一個最小高度,開始就經過js獲取);或者使用top設置高度。
若是,要考慮全部手機中 底部的按鈕必須離底部相同的距離。這個可能就要使用js獲取 沒有鍵盤時屏幕的高度。而後把 定位參考 元素高度設置爲這個值。
頁面能夠滾動:這個比較簡單,沒有鍵盤時,頁面高度已經 大於 容器的高度了。呼起鍵盤後仍是滾動的。沒有任何的問題。
b、軟件盤喚起,在表單 外滑動,軟鍵盤不關閉,點擊纔會關閉(這點表現,二者是同樣的,沒有兼容性問題,記錄下這個特性)。
c、軟件盤的關閉方法,表單失去焦點 / 軟件盤上的關閉按鈕 (這點表現,二者是同樣的,沒有兼容性問題,記錄下這個特性)
d、點擊軟鍵盤上的關閉按鈕、安卓手機不會觸發 表單的 blur 事件,ios能夠。(安卓的問題)
須要 軟件盤關閉時 執行代碼,在安卓上就須要作兼容處理。(解決安卓的一些兼容性問題,必需要在軟鍵盤關閉時執行。如鍵盤拉起時,會把底部fixed元素移上去的,須要作一個判斷進行隱藏;關閉軟鍵盤時,再顯示)
e、軟鍵盤喚起時fixed 元素失效(ios的問題):以下說明
四、 軟鍵盤呼起時fixed失效(fixed+input,ios的問題):(有一個inobounce插件,能夠直接解決這個問題。功能上至關於使得畫布的高度,始終等於鍵盤上面到頂部的高度。無論鍵盤有沒有出來都這樣。有時間能夠看下源碼)
a、頂部 fixed元素,input框在頂部:點擊這個input框,fixed雖然失效了,可是頁面不會滾動。fiexd元素會滾動是由於軟鍵盤的彈出,fixed失效了(或變成了absolute),只要input失去焦點時,馬上把鍵盤關閉,fixed元素就沒有滾動的機會。
這樣就能夠解決fixed無效的問題了。
中間部分有滾動部分的解決方案,有效 https://www.iteye.com/blog/570109268-2406086(解決了中間滾動部分的高度,不會引發畫布的滾動。畫布的滾動,仍是會使fixed滾動,這個解決方法就是上面說的失去焦點,隱藏鍵盤)
b、底部 fixed元素,input框在底部:這個input輸入框,點擊這個輸入框,頁面都會向上滾動的。input框始終在鍵盤上面,鍵盤關閉,滾上去的頁面也不會滾下來。
這個 當表單失去焦點時(或觸發鍵盤隱藏事件時),讓頁面滾動到以前的位置就能夠解決:
document.documentElement.scrollTop = 100; // 這個值是彈出鍵盤前的位置
inobounce 禁止IOS H5的滑動回彈 :https://blog.csdn.net/weixin_30610755/article/details/95260237
五、解決頁面,返回時重複的問題 (重要,app中返回是常常會用到的,因此瀏覽器歷史記錄須要頁面控制下。頁面前進或回退時,url只是參數的改變,頁面是不刷新的)
A(列表頁) =》 B(詳情頁,B中有跳到A頁面的按鈕):列表A1 =》 B 點擊跳到A的按鈕 =》
列表A2 =》B。這個時候回退時,B=》A=》B=>A 會出現不斷重複的問題
解決方案:使用vue路由的 vm.$router.replace() 方法跳轉,或 原生的 location.replace(URL)
六、input中佔位文字,沒法上下居中對齊(應該是字體小於12px,引發的問題)。
七、ios監聽軟鍵盤確認按鈕:會無效(那個 確認 按鈕會變化 爲換行 按鈕,換行時,監聽key=13是對的。變成確認時,監聽不了key=13的這個鍵。【猜想可能同一個鍵,確認的鍵盤碼不是13】)
解決辦法: type="search" 的輸入控件,會使改變軟鍵盤確認按鈕的文字變成搜索(且鍵盤碼都是13)。https://blog.csdn.net/sinat_24070543/article/details/53423274
<form action=""> // form 標籤必須加 <input v-model="wordName" type="search" placeholder="輸入垃圾名稱搜一搜" @input="inputText" ref="input"/> </form>
這個方法能夠不用監聽key=13事件,直接監聽form的 submit 事件一樣能夠監聽 確認按鈕。
(項目中是 在 搜索框 右邊加一個 搜索按鈕,不使用軟鍵盤上的確認按鈕)
另:type=search表單,輸入文字後,右邊會有一個刪除文字按鈕的。解決方案:https://www.cnblogs.com/xiaoshen666/p/10772858.html
input[type="search"]::-webkit-search-cancel-button{ -webkit-appearance: none; }
八、小高度標籤內 單行文本 垂直居中 偏上的解決方案(安卓設備上):https://blog.csdn.net/zhanghuanhuan1/article/details/80339610 或 http://www.javashuo.com/article/p-tmcpygqp-mq.html(推薦)
緣由(我的猜想):移動端是支持12px如下的字體的。安卓上小於12px的字體,字體會溢出標籤一點。親測,以下圖,設置了居中的樣式,字體設置爲10px,字體溢出他的包含標籤sapn。即,
瀏覽器12px如下的字體 以12px顯示;移動端小於12px的字體,也能夠正常顯示,可是排版有點小問題(會上移)。
常規的居中方案都沒有用的,使用scale能夠近似解決,可是不夠完美。目前沒有其餘的可行方法。或者使用媒體查詢,小於12px的尺寸,就以12px顯示。折騰了很久,找不到好的辦法
九、ios上vue框架中返回 keep-alive 的頁面(這個頁面比較長,有滾動。滾到頂部,進入下一個頁面),會出現白屏(被什麼東西遮擋住了)。手輕輕滑動下,遮擋層就消失了。
緣由及解決方法:http://www.javashuo.com/article/p-mqsdltvc-nm.html (公司的項目中由於是多人開發,很差動html, body的屬性。因此沒用這個解決方案,只是不用 keep-alive 了)
十、ios中 h5頁面 輸入框點擊空白處不會失去焦點 軟鍵盤不會收起(重要):
解決方案:https://www.cnblogs.com/gd-dql/p/7476330.html(親測有效,裏面使用touchend觸發,改爲touchstart更好。有時間整理下,把裏面的定時去掉)
十一、ios-H5 中,不過頁面的高度是多少(html,body設置爲50px,只有一個input標籤),只要鍵盤彈出,頁面就必定會滾動 。經過上面的方法,input失去焦點立刻隱藏鍵盤。這樣活動的時候鍵盤隱藏,頁面就不會滾動了。
可是,在input內部滑動,仍是會帶動頁面滾動的,給input標籤添加一個touchmove阻止默認事件。就完美了
document.getElementById('input').addEventListener("touchmove",function(event){ event.preventDefault() },false)
(直接讓頁面不滾動,暫時沒有找到解決方案,由於html,body的高度根本沒有超出鍵盤的範圍。我想應該是有直接的解決辦法的,百度H5頁面,不知道是怎麼解決的,有時間研究下)
十二、禁止 ios 頁面上下滾動回彈(橡皮筋效果):沒有橡皮筋效果,就不會出現fixed失效的問題。
解決方案一、使用 inobounce.js 插件(親測有效)。可是 整個頁面都不能滑動了,有溢出的屏幕的元素也不能滑動的。
若是有須要滑動的元素,須要設置一個height或max-height,還有overflow: auto; -webkit-overflow-scrolling: touch; https://blog.csdn.net/weixin_30610755/article/details/95260237
解決方案二、參考 http://www.javashuo.com/article/p-zkwhbnsh-ma.html (親測,兩個方案都有效)
說明:經過閱讀 inobounce.js 的源碼(源碼代碼量不多),發現 原理就是使用window代理屏幕上的 touchmove 事件( window.addEventListener)。判斷當前觸發的對象是非滾動區域,則阻止事件的默認行爲;滾動區域,不阻止事件。
具體實現,插件中考慮的比較全面,比較複雜。直接使用插件是最方便的。
1三、js沒有監聽 手機端軟鍵盤 彈出 / 關閉事件,能夠封裝一個這樣的函數。http://www.javashuo.com/article/p-atnyvqzh-kx.html
安卓 和 ios 對軟鍵盤關閉的行爲是不同的。安卓中 軟鍵盤關閉,webview高度變化(blur事件不必定觸發);ios中 軟鍵盤關閉,觸發 blur事件【或focusout】(webview高度沒有變化)。
1四、 fixed的遮罩層上面能夠滾動,下面內容禁止滾動。 (有時間再單獨研究下,fiexd遮罩層上的事件,如點擊,滾動對下面的內容的影響)
解決方案:移動端開發,body內的元素,最外層的標籤要設置一個高度(通常是容器的高度100vh),溢出屬性設置滾動。不要讓body的高度超過100vh了,否則 fixed的遮罩層上面滾動,下面的內容一會滾動。處理起來比較麻煩。
親測問題:在fixed層上使用vue的 @touchmove.prevent 阻止默認事件,結果上下兩層的滾動都禁止了; 使用 @touchmove.stop 阻止冒泡事件,結果無效。
問題分析:
a、body 的 高度超過 容器高度,body是比較特殊的標籤。fixe層的touchmove事件,會致使body滾動。
b、非 body的標籤,如 div標籤是一個溢出滾動的標籤,其內的一個標籤做爲 fixed遮罩層,則遮罩層內的內容滾動,不會觸發這個div標籤的高度。(我的猜想,遮罩層雖然在div標籤內,可是已經脫離標準文檔流,事件上於div已經沒有關係)
c、body是比較特殊的 標籤,fixed遮罩層內 的 touchmove 仍是會到 body上的。
總結:安卓和ios的兼容性,主要的問題,仍是軟件鍵盤引發的。因此二者關於軟鍵盤的處理必定要讓他們儘量的保持一致。以下要作到一致:
a、輸入框,聚焦時彈出軟件盤。失去焦點時,隱藏軟件盤(ios須要處理的)。
b、ios 的 橡皮筋效果 必定要禁掉(使用 inobounce 插件)。
c、ios 和 安卓 二者 對軟鍵盤關閉 的判斷的邏輯不一樣(軟鍵盤關閉時,執行代碼這個功能是必定會用到的)。如今的手機 不是ios就是安卓手機,能夠把這兩段代碼封裝在一個方法裏,變成一個軟鍵盤關閉的事件(實際開發中,通常只是對一種狀況作出處理)。
if(isIOS){ // 在 ios 中執行下面監聽事件,捕獲 軟鍵盤關閉事件。(isIOS 經過獲取 navigator.userAgent就能夠判斷) window.addEventListener('focusin', () => { // 鍵盤彈出事件處理 alert("iphone 鍵盤彈出事件處理") }); window.addEventListener('focusout', () => { // 鍵盤收起事件處理 alert("iphone 鍵盤收起事件處理") }); }
if(isAndroid){ // 在 android 中執行下面監聽事件,捕獲 軟鍵盤關閉事件 const innerHeight = window.innerHeight; window.addEventListener('resize', () => { const newInnerHeight = window.innerHeight; if (innerHeight > newInnerHeight) { // 鍵盤彈出事件處理 alert("android 鍵盤彈窗事件"); } else { // 鍵盤收起事件處理 alert("android 鍵盤收起事件處理") } }); }
感悟:一、若是不用 輸入框,基本沒有什麼兼容性問題。css的兼容性問題也基本沒有,就幾個默認樣式的區別;沒有軟鍵盤,ios回彈效果也沒什麼影響,能夠不作處理。
二、上面講的安卓和ios上的兼容性問題,都是webview內核的兼容性問題。hybrid-app中SDK方法也會有兼容問題的,這種bug徹底就是安卓和ios軟件開發者沒有(或沒法)統一引發的。通常安卓和ios是不一樣的人開發的。
一樣的微信軟件,在ios上和安卓上清除緩存的功能都是不同的。微信JS-SDK,在處理分享連接連接也是有差別。本身公司開發是「杭州辦事服務」APP,JS調用原生的語音功能也存在兼容性問題。
文章閱讀
一、移動端項目實戰心得: 參考連接
移動端事件: https://www.jianshu.com/p/201518903985(原生的沒有 tap 和 swipe 事件)
一、touch事件:
touchstart:手指觸摸到屏幕會觸發
touchmove:當手指在屏幕上移動時,會觸發
touchend:當手指離開屏幕時,會觸發。
touchcancel:可由系統進行的觸發,好比手指觸摸屏幕的時候,忽然alert了一下,或者系統中其餘打斷了touch的行爲,則能夠觸發該事件。(在瀏覽器的模擬器中觸發touchcancel事件,Alt+Tab鍵)
注意:使用 touchend 事件時,必定要考慮touchcancel事件。好比,語音功能。按下說話,忽然彈出 語音權限未開。這個時候手指拿開就不會觸發touchend事件了,touch事件被打斷了,屏幕上一直是touchstart的狀態。
必須加上 touchcancel 事件,補充 手指拿開後的頁面狀態。
移動端各類高度:(在pc上,瀏覽的高度對用戶基本什麼問題。可是在移動端瀏覽的各類高度問題。好比webview的高度,是否包含軟鍵盤,不一樣的系統有差別性。微信的H5頁面,底部有左右前進按鈕欄,webview的高度是否又包含這個)
參考:http://www.javashuo.com/article/p-kyqdyljr-cw.html 或 https://www.jianshu.com/p/27b68f780054?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation
一、window.outerHeight:【不經常使用】窗口的外部高度,包括全部界面元素(如工具欄/滾動條)。手機端,這個值和innerHeight同樣。
二、window.innerHeight:【通常】瀏覽器窗口高度(包括橫向滾動條的高度,沒有橫向滾動條,和documentElement.clientHeight是同樣的。https://www.cnblogs.com/suihang/p/11177093.html )。(ios中軟鍵盤彈出時,有兩個值)
三、body.offsetHeight:【不用】網頁可見區域高(不肯定具體的含義,值和scrollHeight同樣。)。
四、body.clientHeight(兼容問題):瀏覽器窗口高度(不包括橫向滾動條)。(不一樣瀏覽器表達方式不同,谷歌中他的值無效。使用 documentElement.clientHeight【經常使用】)
五、body.scrollHeight(兼容問題):網頁正文 全文高。能夠理解爲畫布的高度。(谷歌中他的值表示body的高度,使用 documentElement.scrollHeight【經常使用】。https://www.cnblogs.com/nanshanlaoyao/p/5964730.html)
六、body.scrollTop(兼容問題):滾動條在Y軸上的滾動距離,即文檔上邊出去的高度。(谷歌、火狐上都爲0,使用 documentElement.scrollTop【經常使用】 。https://www.jianshu.com/p/4c37a2a56586
)
兼容性解決方案:http://www.javashuo.com/article/p-vocykzuq-s.html
七、window.screenTop:【不經常使用】窗口相對於屏幕的Y座標。即瀏覽器頂部距離顯示器頂部的距離。https://www.w3cschool.cn/jsref/prop-win-screenleft.html
八、screen.height:【不經常使用】屏幕分辨率的高,即顯示器的高度。
九、screen.availHeight:【不經常使用】顯示器除去底部任務欄後的高度。https://www.w3school.com.cn/jsref/prop_screen_availheight.asp
各類高度 | 鍵盤沒有彈出(安卓) | 鍵盤彈出後(安卓) | 鍵盤沒有彈出(ios) | 鍵盤彈出後(ios) | 微信網頁底部左右箭頭欄隱藏(ios) | 微信網頁底部左右箭頭欄顯示(ios) | ||
window.outerHeight | 647 | 380 | 603 | 603 | ||||
window.innerHeight | 647 | 380 | 603 | 603,293(滾動到底部) | ||||
body.offsetHeight | 771 | 771 | 793 | 793 | ||||
body.clientHeight | 771 | 771 | 793 | 793 | ||||
body.scrollHeight | 795 | 795 | 817 | 817 | ||||
body.scrollTop | 0 | 68 | 0 | 0 | ||||
window.screenTop | 0 | 0 | 0 | 0 | ||||
screen.height | 720 | 720 | 667 | 667 | ||||
screen.availHeight | 720 | 720 | 667 | 667 |