1. 程式人生 > >html5移動端開發

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();