html5移動端開發
第一章 APP分類
- native app
- web app
- hybid app
- 移動web(移動web站點,web觸屏版)
第二章 移動端web開發要面對的問題
2.1相容問題
UC、Chrome、Safari、QQ瀏覽器、百度瀏覽器、360瀏覽器等手機上的瀏覽器幾乎全部都是基於webkit核心
2.2適配問題
首先採用百分比自適應佈局(即流式佈局)
同時,需要對一定段的viewprot視口進行設定,就能達到適配的目的
第三章 viewport(視口)
瀏覽器上承載著viewport,viewport承載著網頁。
viewport是一個虛擬的視窗,它支援放大縮小。
3.1viewport是什麼?
在移動端用來承載網頁的一個區域,就是我們的視覺視窗–viewport。這個區域可以設定寬高,可以按比例放大縮小,而且能設定是否允許使用者自行縮放。
viewport有預設的寬高,在iphone4中預設為980px*1000px。二手機螢幕的寬高並沒有這麼多,故此之鞥將網頁縮放顯示在螢幕上,這樣勢必會導致網頁的內容特別小,看不清。
所以現在就需要將viewport設定成和手機螢幕相同的尺寸就OK。設定方法:
<meta name="viewport" content="width=device-width;initial-scale=1.0;user-scalable=no;minimum-scale=1.0;maximum-scale=1.0" >
3.2PC頁面在手機上縮放的原因
- iPhone4中預設的viewport 980px*1000px,user-scalable=yes
- 那麼initial-scale在320px的瀏覽器上就是320/980=0.333333
3.3標準的移動web頁面
使用meta標籤吧viewport的寬度設為device-width,同事initial-scale=1.0,user-scalable=no
3.4viewport引數
- width:寬度設定是viewport的寬度,可以設定device-width特殊值
- initial-scale:初始化縮放比,大於0的數字,一般設為1.0
- minimum-scale:足校縮放比,大有0的數字,一般設為1.0
- maximum-scale:最大縮放比,大於0的數字,一般設為1.0
- user-sacable:使用者是否可以縮放,yes或no(1或0)
第四章 踩過的那些坑
4.1 rgba與opacity
rgba中的第四個值可以設定透明度,它與opacity不同的是,它的透明度設定不會影響盒子中的內容的透明度,而opacity設定之後連內容也隨之變模糊了。
4.2 圖片失真
切圖面對的問題:如果按照1:1的顯示在移動裝置當中圖片會失真。
原因是:在高清屏中會用兩個或兩個以上的物理畫素來顯示實際的1px圖片內容,那麼其實就是相當於把1px的圖片放大顯示了,所以有毛邊的圖片一般都會失真,也就是顯示模糊。
解決方案:採用壓縮圖片尺寸的方式來解決。
如果是img直接設定寬高的方式來壓縮;
如果是background-image設定background-size的方式來壓縮
4.3img基線對齊
基線:abcdyxz這行字母的y底下就會多出一點來,這是因為文字以基線對齊。同樣的,img標籤也是inline-block元素,以基線對齊,底下就會出現一小點空白。
解決方案:
- 方法1:給img設定display:block;
- 方法2:給img的父級設定font-size:0;
- 方法3:給img設定vertical-align:middle
4.4移動端頁面點選穿透
4.4.1click與300ms延遲
移動端瀏覽器提供一個特殊的功能:雙擊(double tap)放大。
300ms的延遲就是來自這裡,使用者碰觸頁面之後,需要等待一段時間來判斷是不是雙擊動作,而不是立即響應單擊(click),等待的這段時間大約是300ms。
移動端事件提供touchstart、touchmove、touchend卻沒有提供tap的支援,主流框架(庫)都是手動實現了自定義的tap事件,以求消除300ms的延遲,提高頁面的響應速度。
4.4.2穿透產生的原因
混用tap和click就會導致點選穿透的問題,因為click是在tap系列事件發生後大約300ms才觸發的。
4.4.3點選穿透現象
1)點選蒙層(mask)上的關閉按鈕,蒙層消失時發現觸發了按鈕下面元素的click事件
蒙層的關閉按鈕繫結的是tap事件,而按鈕下面元素繫結的是click事件,tap事件觸發後,蒙層消失了,300ms這個點的click事件fire,event的target自然就是按鈕下面的元素,因為按鈕跟蒙層一塊消失了。
2)如果按鈕下面恰好是一個href屬性的a標籤,那麼頁面就會發生跳轉。
因為a標籤跳轉預設是click事件觸發。
3)直接點選頁內按鈕跳轉至新頁面,然後發現新頁面中對應位置元素的clic事件被觸發了。
4.4.4解決方案
問題已經很明瞭了,有很多解決方案,但思路不外乎2種:
1)不要混用tap和click
既然tap之後300ms會觸發click,只用tap或者只用click就自然不會存在問題了
2)吃掉(或者說消費掉)tap之後的click
依舊用tap,只是在可能發生點選穿透的情形做額外的處理,拿個東西來擋住、或者tap後延遲350毫秒再隱藏mask、pointer-events、在下面元素的事件處理器裡做檢測(配合全域性flag)等等,能吃掉就行
詳細解決方案:
1)只用touch
最簡單的解決方案,完美解決點選穿透問題
把頁面內所有click全部換成touch事件( touchstart 、’touchend’、’tap’), 需要特別注意 a標籤,a標籤的href也是click,需要去掉換成js控制的跳轉,或者直接改成span + tap控制跳轉。如果要求不高,不在乎滑走或者滑進來觸發事件的話,span + touchend就可以了,畢竟tap需要引入第三方庫
不用a標籤其實沒什麼,移動app開發不用考慮SEO,即便用了a標籤,一般也會去掉所有預設樣式,不如直接用span
2)只用click
下下策 ,因為會帶來300ms延遲,頁面內任何一個自定義互動都將增加300毫秒延遲,想想都慢
不用touch就不會存在touch之後300ms觸發click的問題,如果互動性要求不高可以這麼做, 強烈不推薦 ,快一點總是好的
3)拿個東西來擋住
比較笨的方法, 千萬不要用
4)tap後延遲350ms再隱藏mask
改動最小,缺點是隱藏mask變慢了,350ms還是能感覺到慢的
只需要針對mask做處理就行,改動非常小,如果要求不高的話,用這個比較省力
5)pointer-events
比較麻煩且有缺陷, 不建議使用
mask隱藏後,給按鈕下面元素添上 pointer-events: none; 樣式,讓click穿過去,350ms後去掉這個樣式,恢復響應
缺陷是mask消失後的的350ms內,使用者可以看到按鈕下面的元素點著沒反應,如果使用者手速很快的話一定會發現
4.5iphone全屏佈局問題
開發的頁面在Android上面看時,頁面的頂部是在狀態列以下的位置的,而在ios上面看時,頁面的頂部和狀態列頂部對齊了,即頁面上邊部分內容被狀態列擋住了,出現這個問題的原因是iphone講求“全屏佈局”。
解決問題的辦法就是:
在一個公共的(每個頁面都需要引入)js檔案中,加入以下程式碼,動態判斷當前是不是IOS系統,如果是,則在頁面頂部加入大約15px高度的一個div
var u = navigator.userAgent;
var isAndroid = u.indexOf('Android') > -1 || u.indexOf('Adr') > -1; //android終端
var isIOS = !!u.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/); //ios終端
if(isIOS){
var perDiv = '<div style="width:100%;height:1.5rem;background:#19273F;position:fixed;z-index:10;top:0;"></div>';
$(".sinoiov-bar-nav").before(perDiv).css("top","1.4rem");
$(".sinoiov-has-header").css("margin-top","6.3rem");
}
4.6 reset css
*,::before,::after{
margin:0;
padding:0;
/*清楚移動端預設點選高亮*/
-webkit-tap-heightlight-color:transparent;
/*因為使用百分比佈局,如果加上padding或者border,就有可能超出螢幕寬度,故設定盒子尺寸以邊框開始計算*/
-webkit-box-sizing:border-box;
box-sizing:border-box;
}
body{
font-size:16px;
font-family:"MicroSoft YaHei",Sans-Serif;
color:#333;
}
a{
color:#333;
text-decoration:none;
}
a:hover{
text-decoration:none;
}
ul,ol{list-style:none;}
input{
border:none;
outline:none;
/*清除移動端預設表單樣式*/
-webkit-appearance:none;
}
4.7 common css
.left{float:left;}
.right{float:right;}
.clearfix::before,.clearfix::after{
content:'';
height:0;
line-height:0;
display:block;
visibility:hidden;
clear:both;
}
4.8導航欄左側的返回按鈕
可以使用JavaScript中的history.go(-1)
的方式實現返回按鈕,但是這樣做有很大的侷限性。就是隻能是一級一級向上返回,有時候業務邏輯並不是一級一級返回的。最常見的場景就是充值,付款時。
這時就需要自己實現上述功能。實現的思路是每請求一次URL,判斷棧最後面的URL是否等於當前的URL,如果不等於,則就向棧中push當前的URL,如果等於,則什麼都不做;點選返回按鈕時,pop掉棧中最後一個元素,並重定向到棧中的最後一個URL。
(function(){
function Vehicle(){}
Vehicle.prototype = {
setHistory:function(url){
var historyArray = JSON.parse(localStorage.getItem("historyArray"));
if(!historyArray){
historyArray = [];
historyArray.push(url);
}else{
if(historyArray[historyArray.length -1] != url){
historyArray.push(url);
}
}
localStorage.setItem("historyArray",JSON.stringify(historyArray));
},
goBack:function(){
var historyArray = JSON.parse(localStorage.getItem("historyArray"));
if(historyArray.length > 1){
historyArray.pop();
localStorage.setItem("historyArray",JSON.stringify(historyArray));
}
window.location.href = historyArray[historyArray.length-1];
}
};
window.vehicle = new Vehicle();
})();
localStorage.clear();
window.vehicle.setHistory(window.location.href);
window.vehicle.goBack();