淘寶彩票移動項目開發實踐

jopen 12年前發布 | 49K 次閱讀 移動開發

作者按:如今越來越多的互聯網產品開始在移動終端發力,終端產品越來越豐富。但是,平臺差異帶來的開發成本浪費很讓人頭疼。一段時間以來,淘寶彩票前端組也在努力尋求移動終端項目開發最佳實踐,盡管諸多方面不甚成熟,但拋磚引玉,希望我們的總結整理會對大家有所啟發。

        淘寶彩票客戶端產品目前有兩條體系:

  1. 原生應用:包括 iPhone 和 Andoird 上原生的客戶端應用
  2. 嵌入式應用:作為子應用的軟件包形式提供,嵌入到第三方的客戶端軟件中,比如淘寶主站客戶端以及支付寶客戶端等
  3. </ol>

            由于產品的共通性,這兩類應用都是需要考慮較多復用性和開發成本的。在原生 App 中,有不少內容是可以用簡單的 HTML5 來實現的,比如 iPhone 客戶端中的“訂單頁”:

    淘寶彩票移動項目開發實踐淘寶彩票移動項目開發實踐

            而在子應用的軟件包里,則有更多的地方可以運用 HTML5 來實現,包括一些復雜的富交互。例如支付寶客戶端中各彩種的實現:

    淘寶彩票移動項目開發實踐淘寶彩票移動項目開發實踐

            App 的形式

            目前移動終端上的應用主要以 Native App 為主,這種應用的優勢是:

            1,性能快,體驗好;

            2,可訪問本地資源,更有效的利用設備,節省流量;

            3,并且已有一定規模(App Store),付費模式明朗。

            缺點是:

            1,開發成本高,移植性差;

            2,所有發布需要經過 App Store 的審核。

            當然,目前還存在一些 Web App,用戶可以直接通過瀏覽器來訪問,例如 Gmail。這類 App 的開發和維護的成本低,可以天然的在各種終端上執行,并且容易迭代更新,無需用戶進行安裝。不過就現階段而言,無論從速度上還是交互上,用戶體驗與 Native App 的差距還是比較大的。既然兩種 App 都各有利弊,那么我們就干脆將二者相結合:用原生控件做外殼和交互,保證流暢的用戶體驗和完整的推廣渠道;使用 HTML5 來展示內容,保證內容的迅速迭代更新,即時響應用戶需求。于是就誕生了 Hybrid  App,這也是目前最流行最合適的一種 App 形式。

            對于前端工程師而言,在移動平臺上沒有了 IE 系列的困擾,HTML5的很多特性都可以大膽的運用。不同的是,我們需要設置一些針對移動終端的 Meta 屬性,以及更合理的利用 Media Query(主流移動設備的分辨率信息)。

            JS 框架的選擇

            找到適合使用 HTML5 的場景,這時就需要考慮 JS 框架的選擇。首先需要明確的是,類似 jQuery 和 YUI 這種“重型”的庫,由于包含了很多處理兼容性方面的代碼,且 API 設計過于細致而顯得太過龐大,并不適合移動端。我們可以選取一些專業的用于 Mobile 開發的 JS 類庫,例如 jQuery Mobile,Sencha Touch 等。jQuery Mobile 是目前最流行的一個移動開發的框架,文檔豐富,社區活躍,有很多的 UI 控件供我們使用,并且提供對多頁面的支持(通過 Ajax 方式讀取內容,并提供頁面切換的過渡動畫)。我認為 jQuery Mobile 的最強大之處就在于其 UI 方面的支持,但這一部分恰恰不是我所需要的。Sencha Touch 是 ExtJs 的移動版,對于不熟悉 ExtJs 的人來說有一定的學習成本。

            我們選擇了zepto.js作為底層庫,使用sea.js進行模塊的管理和發布,原因是基于 CMD 規范的模塊文件最終需要打包入應用的軟件包里, 或是打包后發布到線上;此外,我們使用backbone.js為基礎的 MVC 架構,用來剝離應用的數據部分;使用underscore.js做為前端模板引擎(backbone 重度依賴);使用iScroll.js為我們提供模擬滾動的功能。這些都是一些專業的“小庫”,很適合移動端的開發。當然,具體情況需要具體分析,沒有萬能的框架,只有萬能的開發者。如果時間允許,也可以自己來定制一套滿足自身需求的基礎庫。畢竟在移動端,一切以 “精簡”為主。

            應用架構的選擇

            首先拋出兩個小問題:

            1、  OPOA 近兩年來在互聯網得到了廣泛應用,相比于之前的多頁面切換和跳轉的方式,這個方法也更優雅,用戶體驗更好。那么在移動端,OPOA 是否依舊適用呢?

            2、HTML5最大的優勢就是跨平臺,只需要開發一套代碼,就可以完全通用于不同的終端。但是,真的一套代碼就能“吃”盡所有移動終端么?

            先解答第一個問題。其實我們在開始嘗試的時候,完全是參照 PC 端的 OPOA 來進行的,把很多的內容都放在一個 Page 里面,通過 URL 或 Hash 的方式來管理頁面的顯示。但實踐表明,在移動端這樣做是有很大弊端的。首先,在 PC 上顯示區域比較大,我們可以先給用戶展示一個框架,然后在分塊的去顯示內容,但是移動終端由于屏幕變小,往往同時只能展示一個區域,那么我們首先要根據 URL 判斷顯示哪個區域,然后再去加載這個區域的內容, 這樣一來,讓本來在移動端就變慢了許多的頁面更加的雪上加霜。其次,為了減少請求,我們通常會把大量的前端模板都塞到這個僅有的 Page 中,不僅導致頁面體積變大,性能降低,而且維護困難。因此,我認為,在移動端最好的方式還是傳統的多頁面開發。

            那么肯定有人會問,這樣子的話豈不是會損失頁面切換的流暢性,讓用戶不爽么。這個問題我們是可以解決的。第一就是采用 jQuery Mobile 的方式(Web App 中非常適用),切換時用 Ajax 去請求新的內容,然后再渲染到頁面中。這種方法在某些特定條件下會有問題:我們仍然需要使用 URL 來進行歷史的管理,如果將這些頁面作為靜態文件打包在客戶端中的話,在一些 Android 系統的手機中,硬件會將這些帶后綴的文件當成一個完整的文件去查找(例如 index.html?page=XXX),然后發生錯誤。第二個方法就是在 Hybrid  App 中,我們可以借助客戶端來幫助我們進行頁面的切換。你只需要告訴客戶端即將要跳轉的 URL 路徑(可以是網絡請求,也可以是本地靜態文件),然后由客戶端進行跳轉。這樣就可以在客戶端代碼里面設置 Webview 切換的動畫效果,使客戶端的整體風格更加的統一。

            針對第二個問題,我們剛開始的目標就是用一套代碼來自適應所有的客戶端。結果發現,在 iPhone 和 Android 上,盡管風格差別較大,但是整體的結構和布局是很相似的,那么只需要設置兩份 CSS 文件,再提供一份 API,分別在兩個平臺上做實現就可以了,維護起來很方便;但是在 iPad 上,由于布局和交互變化比較大,為了復用,不得不在原代碼上增加分支,不但破環了原代碼的完整性,而且維護時會產生一些意想不到的錯誤。這樣就得不償失 了。因此,如果手機客戶端和平板電腦客戶端差異很大的話,最好還是分開單獨進行處理,而不是為了“復用”而復用,大家可以根據具體的情況制定自己的策略。 例如彩票的 iPad 客戶端,我們就是純粹基于 HTML5 為 pad 量身定做的:

    淘寶彩票移動項目開發實踐

            Webview 及其與 HTML5 的通信

            Webview 是手機中內置的一個基于 webkit 內核的 SDK,是搭載 Web 頁面的容器,也是負責 Web 頁面和 Native App 之間相互通信的橋梁。在不同平臺上 Webview 的實現是有較大差異的。

            在 Android 平臺中是支持 JS 方法和 Java 方法的直接調用的,我們通過下面的代碼即可實現互相調用。

    //將 JAVA 對象綁定到 JavaScript 中

    mWebView.addJavascriptInterface (new JsToJava (), 'stub');

    //在 JavaScript 中調用 Java 方法

    window.stub ();</pre>

    -

    function invokedByJava (data){

      //do something
    
    

    }

    //在 Java 中調用 JavaScript 方法

    public void onClick (View v) {

      mWebView.loadUrl ("javascript:invokedByJava ('java_data')");
    
    

    }

    //打開 webview,調用頁面

    mWebView.loadUrl ("file:///xxx.html");</pre>

            但在 iOS 平臺上,SDK 沒有原生提供 JavaScript 調用 Native 代碼的 API,只有反向調用的方法。要想在 JavaScript 中調用 Native,一般有兩種方法:一種是 Phonegap 采用的 iframe 方法,也是比較推薦的,如下所示;另一種是直接修改頁面的 location,在大部分情況是可用的,但是有時候會產生一些莫名其妙的錯誤。這兩種方法的原理都是相同的:利用 Webview 去截獲 JS 發起的特殊的網絡請求,然后對其進行處理。

    //Objective-C

    • (BOOL) webView:(UIWebView ) webView shouldStartLoadWithRequest:(NSURLRequest ) request navigationType:(UIWebViewNavigationType) navigationType {
        NSURL * url = [request URL];
        if ([[url scheme] isEqualToString:@"gap"]) {
            //在這里做 js 調用 native 的事情
            //...
            //完成之后回調 js
            //[webView stringByEvaluatingJavaScriptFromString:
                       @"alert ('done')"];
            return NO;
        }
        return YES;
      
      }

    //通知 iPhone UIWebView 加載 url 對應的資源,url 格式為: gap:something function loadURL (url) { var iFrame; iFrame = document.createElement ('iframe'); iFrame.setAttribute ('src', url); iFrame.setAttribute ('style', 'display:none;'); iFrame.setAttribute ('height', '0px'); iFrame.setAttribute ('width', '0px'); iFrame.setAttribute ('frameborder', '0'); document.body.appendChild (iFrame); //發起請求后將其從 DOM 上移除 iFrame.parentNode.removeChild (iFrame); iFrame = null; };</pre>

            除此之外,不同平臺的 Webview 還需要進行一些特殊的設置,才能讓其和原生的瀏覽器的行為表現相一致。例如:在 Android Webview 中,JavaScript 和 localStrorage 都是默認禁止的,需要提前啟用;Android 的物理后退鍵默認是會關閉當前的 Bebview 的,而不是執行 history.back ();在 iOS5.0 以下的系統中,設置格式檢查的 Meta 屬性會偶爾失效,需要在 Webview 中直接關閉其格式檢查等等。在 D2 沙龍的 PPT 中有詳細的描述,大家有感興趣的可以看下。

            速度/性能

            對于一個互聯網產品的用戶體驗來說,速度和性能幾乎是最重要的因素。但令人遺憾的是,這也是目前阻礙 Web App 發展的最大的障礙。原因主要有以下幾個方面:

            1    低端設備多,受硬件的限制。根據木桶原理,一個木桶的水量是受最短的板的限制的。與之類似,我們在衡量頁面性能的時候,也需要看其在中低端 機型上的表現,尤其是廣大的 Android 千元智能機。如果 Android 所有的機型都能有 Samsung Galaxy 的表現,我們也就不用愁眉苦臉了,但是在更多時候,我們不得不為了在 HTC 野火上能夠正常的展示而放棄在 Samsung 上看起來非常帥氣的效果。

            2    簡化的瀏覽器實現。本來相比桌面版的瀏覽器,移動版的瀏覽器已經在功能上做了一些簡化,性能上有些差距。但是,與原生的移動瀏覽器相 比,Webview 會更慢。下圖為一個頁面分別在 Mobile Safari 和 非死book 的 iPhone 客戶端中的運行結果,我們可以發現,UIWebView 中的 JS 運行時間大概是 Mobile Safari 的3-4倍,這恐怕也是 非死book 放棄 HTML5 轉向原生應用的一個原因之一。

    淘寶彩票移動項目開發實踐

            針對上述原因,我們總結出一些性能優化的小 Tip:

            1    用 HTML5 的離線存儲和本地存儲進行緩存,或者將頁面直接打包到客戶端中,減少在網絡下載中的耗時。

            2    減少 DOM 數量,盡可能少的使用 position:relative,減少對 DOM 的操作

            3    用 CSS 動畫代替 JS 動畫,在 Android 平臺上可以平穩退化,放棄動畫效果(包括 CSS3 動畫)

            4    避免 GIF 圖片的使用(消耗內存)

            5    如果只是在移動端使用的話,請使用 iScroll-lite 來代替 iScroll(iScroll 里面增加了很多額外的功能,比如在 PC 上模擬滾動),在允許的情況下,可以關閉滾動條(滾動條也是創建的 DOM 元素)

            關于滾動,還有一些其他的想法,大家有興趣可以一試:

            1、將頁面拆分成多個 Webview,這樣子在每個 Webview 中就都是原生的實現了,但會增加一些頁面間互相通信的代價。

            2、用 Canvas 來代替 Scroll,但是文字的渲染可能會有些問題。

            由于篇幅原因,這里就不贅述更詳細的性能問題了~

            移動終端的網絡環境

            移動應用最大的特點就是方便、隨處可用。但無論是 2G 還是 3G,我國目前的網絡狀況都難以滿足移動應用的要求。相比于 Native App,Web App 除了要下載數據和圖片外,還需要下載一些額外的 js/css 文件,這些動輒上百K的靜態文件對于平均速度還不到 10K 的 2G 網絡來說實在是太龐大了。 因此,目前最好的應用場景還是將頁面打包到客戶端中,版本變化時提醒用戶讓其主動進行更新。盡管這樣會損失一部分 web 頁面的靈活性。

            調試

            開發時的調試相對方便,可以基于瀏覽器進行。但開發環境和最終的執行環境還是有一些差異的,需要對終端的 View 中的“頁面”進行調試,現在我們的做法是 “打點”,即使用一個 Log 代理控件給代碼埋點,輸出 log,以此來輔助我們的調試。目前常用的工具有 Weinre 和 JSconsole 等。這些工具的原理是比較類似的:通過網絡在其他機器上連接了一個調試的 GUI,捕獲待調試網頁的 JavaScript 運行環境來查看代碼輸出或者對代碼求值,并可以監控和修改調試目標的 DOM 和 CSS 樣式。但是由于調試不是真正的發生在移動設備上,所以無法設置和捕捉斷點進行 debug。

            在最新的 iOS6 中,Safari(僅限 Mac 桌面版)中自帶了 web 檢查器工具,可以讓我們更方便的對 iPhone/iPad 上的 Safari 進行遠程調試。

 本文由用戶 jopen 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!