非響應式設計構建跨端Web App
對于Web開發人員來說,如果要通過對樣式表進行微調來為不同尺寸設備的用戶提供更好的體驗,媒體查詢(Media Queries)非常棒。 媒體查詢實質上可以根據屏幕的尺寸來自定義網站的CSS。在你深入這篇文章之前,可以更多的了解響應式網頁設計(還記得《用3個步驟實現響應式網頁設計》這篇文章嗎?) ,并且看看使用媒介查詢的一些好例子: mediaqueri.es 。
像布拉德·弗羅斯特在以前文章中指出的一樣,調整界面只是構建移動Web App時需要考慮的眾多事情之一。 如果你在構建移動Web App時只通過媒介查詢自定義了布局,那么我們會有以下的問題:
所有的設備都采用同樣的JavaScript、CSS以及內容(圖片、視頻等),導致產生比預期更長的加載時間。
所有的設備都有相同的初始DOM結構,可能迫使開發人員編寫過于復雜的CSS樣式。
對于為每個設備指定自定義的交互來說缺乏彈性。
除媒介查詢外,Web APP還需要更多
不要誤會我的意思。我并不是討厭通過媒介查詢進行響應式設計,并絕對認為它占有一席之地。此外,上述的一些問題可以通過例如響應式圖像 ,動態腳本加載等來解決。但是就某一點而言,你也許會發現自己做了太多的增量調整,而可能提供不同的版本效果會更佳。
當構建的界面在復雜性方面有所增加,同時被單頁的Web App所吸引,你會想要為每個設備類型自定義用戶界面做更多事情。本文將教你如何用最少的努力實現這樣的自定義。通用的方法包括將訪問的設備劃分到正確的分類,并且為該設備提供合適的版本,同時最大限度地提高代碼在版本之間的重用。
針對哪些設備類型?
現在有成千上萬的互聯網設備,幾乎每一個都有瀏覽器。復雜之處在于它們的差異性:蘋果筆記本,Windows工作站,有觸摸輸入、滾輪、鍵盤和語音輸入的iPhone手機,iPad和Android手機,帶壓力傳感器的設備,智能手表,烤面包機以及冰箱等等。它們無處不在,而且有些非常罕見。
各種各樣的設備
為了創造良好的用戶體驗,你需要知道誰是你的用戶以及他們使用的是什么設備。如果你為桌面用戶創建了一個使用鼠標和鍵盤的界面,并將它展示給智能手機用戶,這將是一個極大的失敗,因為它設計在另一個屏幕大小和輸入方式之上。
這里有兩種極端的方法:
1. 創建一個為所有設備工作的版本。用戶體驗將因此受到影響,因為不同的設備有不同的設計考慮。
2. 為每一個要支持的設備各自創建一個版本。這個工作將永遠進行下去,因為你將為你的應用構建太多版本。此外,當新的智能手機誕生(大約每周都有)時,你將被迫再次創建一個版本。
這里有一個基本的權衡:有更多的設備類別時,你可以提供更好的用戶體驗,但是需要做更多設計,實現和維護的工作。
為每種設備創建單獨的版本對于性能原因來說也許是一個好辦法,或者你想為不同的設備創建的版本差異甚巨。否則, 響應式網頁設計會是完全合理的做法。
一個潛在的方案
這里有一個妥協方案:將設備分類,并為每個種類提供最佳體驗。選擇什么類別取決于你的產品和目標用戶。下面是一個示例,能夠很好的跨越現今流行的網絡設備。
1. 小屏幕+觸摸(主要是手機)
2. 大屏幕+觸摸(主要是平板)
3. 大屏幕+鍵盤/鼠標(主要是臺式機/筆記本電腦)
這只是許多可能的分類方式之一,但在寫作時有很大的意義。上面的列表中缺少的是沒有觸摸屏的移動設備(例如功能手機,一些專用的電子書閱讀器)。然而,這些設備大部分都有鍵盤或者屏幕閱讀軟件,如果你的站點精心設計,可以在上面工作良好。
#p#
特定外形的WEB App例子
有許多針對不同因素提供不同Web服務版本的例子。谷歌搜索是這樣,Facebook也是。這主要是考慮了到性能(獲取資源,渲染頁面)和更通用的用戶體驗。
在Native App的世界里,許多開發者選擇為不同種類的設備設計產品。 例如,Flipboard iPad版本的UI與iPhone版本差異很大。平板版本為雙手使用和水平旋轉進行了優化,而手機版本關注單手交互和垂直翻轉的體驗。許多其他的iOS應用在手機和平板上也有明顯的不同,例如Things(Todo list)和如下所示的 Showyou (社會化視頻):
針對手機和平板定制的UI
方法#1:服務器端檢測
在服務器端,我們要了解正在處理的設備有更多的限制。每次請求發送的User-Agent頭所提供的user agent(用戶代理)字符串可能是最有用的線索。正因為如此,相同UA的嗅探方法會產生作用。事實上,DeviceAtlas和WURFL項目已經開始這樣做了(并提供了一大堆設備有關的其他信息)。
不幸的是目前這些項目都存在挑戰。WURFL非常龐大,包含20MB的XML,可能為每個請求導致明顯的服務器開銷。有項目因為性能方面的原因分割了這些XML。DeviceAtlas并不開源,需要付費使用。
這里有更簡單,而且免費的替代品,例如檢測移動瀏覽器項目。當然,缺點是設備檢測難免會不夠全面。 此外,它只區分移動和非移動設備,以及通過ad-hoc軟件提供有限的平板支持。
方法2:客戶端檢測
使用特性檢測,我們可以了解更多用戶瀏覽器和設備的信息。我們需要確定的要點是,該設備是否具有觸摸功能,以及它的屏幕是大是小。
我們需要畫一條線來區分屏幕大和小的觸摸設備。例如像5寸Galaxy Note的邊緣情況。下圖顯示了許多流行的Android和iOS設備輪廓(附上相應的屏幕分辨率)。星號表示該設備可以支持雙倍密度。雖然像素密度可能會增加一倍,CSS仍然會報告相同的大小。
對CSS里像素點的快速介紹:手機Web頁面上的CSS像素和PC上并不一樣。iOS視網膜設備引入了雙倍像素密度(例如iPhone 3GS對iPhone 4,iPad 2對iPad 3)。視網膜設備上Safari瀏覽器的用戶代理仍然報告相同的設備寬度,以免破壞網頁。當其它設備(例如Android)采用了更高分辨率的顯示屏時,它們也采用了相當的解決方案。
設備的分辨率
這種方式會更復雜,但是這對考慮同時兼容縱向和橫向模式非常重要。我們不希望每次屏幕旋轉時都重新加載頁面或者加載額外的腳本,雖然我們可能要呈現不同的頁面。
下圖中,正方形代表每個設備的最大尺寸,是疊加了縱向和橫向輪廓的結果:
橫向+縱向分辨率
通過將閾值設置為650px ,我們將iPhone,Galaxy Nexus分類為小觸摸屏設備,而將iPad,Galaxy Tab分類為“平板”。跨界的Galaxy Note在這種情況下被歸類為“手機”,將采用手機布局。
所以,一個合理的策略可能看起來像下面這樣:
- if (hasTouch) {
- if (isSmall) {
- device = PHONE;
- } else {
- device = TABLET;
- }
- } else {
- device = DESKTOP;
- }
趕快看看一個小的示例特性檢測方法吧。
另一種方法是使用用戶代理嗅探來檢測設備類型,基本上就是創建一套試探方法來匹配用戶的navigator.userAgent。偽代碼看起來像這樣:
- var ua = navigator.userAgent;
- for (var re in RULES) {
- if (ua.match(re)) {
- device = RULES[re];
- return;
- }
- }
馬上來看看一個示例-UA檢測方法。
#p#
在客戶端加載的說明
如果你正在服務器上檢測用戶代理,你可以在收到新請求時決定提供哪種CSS,JavaScript和DOM節點。然而,如果你正在采用客戶端檢測,情況則更為復雜。你有如下幾種選擇:
1. 重定向到特定設備類型的URL,其中包含該設備類型的版本。
2. 動態加載設備特定類型的內容。
第一種方法很簡單,需要采用window.location.href = '/tablet'這種重定向的方式。然而,URL地址會附加設備類型的信息,所以你可能想使用HTML5的歷史API來清理網址。不幸的是,這種方法涉及一個重定向,所以可能會很慢,尤其是在移動設備上。
第二種方法實現更加復雜。你需要一種機制來動態加載CSS和JS,還有(根據瀏覽器而定)你可能無法實現例如自定義<meta viewport> 這樣的事。此外因為沒有重定向,你需要在一張頁面上來響應請求。當然,你可以用JavaScript來實現,但是這可能導致性能緩慢和/或糟糕的代碼,這一切都取決于你的應用程序。
選擇客戶端或服務器方案
下面是在這些方法之間的權衡:
選擇客戶端 :
基于屏幕尺寸或可擴展性的方案和用戶代理比起來更為長遠。
無需不斷更新用戶代理名單。
選擇服務器 :
能完全控制什么設備上加載什么版本。
更好的性能:無需客戶端重定向或動態加載。
我個人的偏好是,最開始使用device.js和客戶端檢測。 隨著應用的發展,如果發現客戶端重定向有明顯的性能問題,你可以很容易地刪除device.js腳本,并在服務器上執行用戶代理檢測。
#p#
DEVICE.JS介紹
device.js是一個起點,這樣做基于語義,依靠媒介查詢進行設備檢測,從而無需特殊的服務器端配置,節省了需要實現用戶代理字符串解析的時間和精力。
這個方法是在<head>標簽的頂部用搜索引擎友好的標記(linkrel=alternate)聲明你要提供的網站版本。
- <link rel="alternate" href="http://foo.com" id="desktop"
- media="only screen and (touch-enabled: 0)">
接下來,你可以采用服務器端UA檢測和版本重定向,或者使用device.js腳本來執行基于功能的客戶端重定向。
更多詳細信息,請參閱device.js項目頁面 ,同時還有一個使用了device.js進行客戶端重定向的測試應用。
建議:MVC的具體視圖
現在你可能會想,我告訴你的是建立三個完全獨立的應用程序,每個用于一種設備類型。不! 代碼共享是關鍵。
希望你已經使用了一個類MVC的框架,例如Backbone,Ember等等。如果你已經熟悉重點分解的原則,尤其是你的用戶界面(視圖層)應該與邏輯(模型層)分離。如果你對此還比較陌生,可以開始了解MVC的一些資源和JavaScript中的MVC 模式。
跨設備非常適合現有的MVC框架。你可以輕松地移動視圖到獨立的文件,為每個設備類型創建一個自定義視圖。然后你就可以為所有設備使用除了視圖層之外同樣的代碼。
跨設備的MVC模式
你的項目可能有以下的結構(當然,你可以自由選擇對你應用最有意義的結構):
- models/ (shared models)
- item.js
- item-collection.js
- controllers/ (shared controllers)
- item-controller.js
- versions/ (device-specific stuff)
- tablet/
- desktop/
- phone/ (phone-specific code)
- style.css
- index.html
- views/
- item.js
- item-list.js
這種結構使你能夠完全控制每個版本加載哪些內容,因為你必須為每個設備采用自定義的HTML,CSS和JavaScript。這非常強大,是開發跨端Web App最精簡和最有效的方式,不會依賴于一些小的技巧,例如自適應圖像。
一旦你運行喜歡的構建工具,會把所有的Javascript和CSS合并和壓縮到一個獨立的文件里,以實現更快的加載速度,而輸出的HTML頁面看起來類似以下的形式(在手機上,使用device.js):
- <!doctype html>
- <head>
- <title>Mobile Web Rocks! (Phone Edition)</title>
- <!-- Every version of your webapp should include a list of all
- versions. -->
- <link rel="alternate" href="http://foo.com" id="desktop"
- media="only screen and (touch-enabled: 0)">
- <link rel="alternate" href="http://m.foo.com" id="phone"
- media="only screen and (max-device-width: 650px)">
- <link rel="alternate" href="http://tablet.foo.com" id="tablet"
- media="only screen and (min-device-width: 650px)">
- <!-- Viewport is very important, since it affects results of media
- query matching. -->
- <meta name="viewport" content="width=device-width">
- <!-- Include device.js in each version for redirection. -->
- <script src=”device.js”></script>
- <link rel=”style” href=”phone.min.css”>
- </head>
- <body>
- <script src=”phone.min.js”></script>
- </body>
需要注意的是(touch-enabled: 0)媒介查詢并不標準(只有Firefox通過moz前綴實現了),但是能夠被device.js正確運行(感謝Modernizr.touch)。
版本覆蓋
設備檢測有時候有誤,在某些情況下,用戶可能更喜歡在手機上采用平板布局(也許他們正在使用Galaxy Note),所以一定要向用戶提供版本的選擇。
通常的做法是提供一個從桌面到移動版本的鏈接。這很容易實現,device.js通過device的GET參數來支持此功能。
結論
綜上,當需要建立跨設備單頁的用戶界面時,并不適合響應式設計,我們可以這樣做:
1. 挑選一系列設備分類進行支持,并為設備分類設定標準。
2. 建立你的MVC應用,把界面從代碼庫分離出來。
3. 使用device.js進行客戶端設備分類檢測。
4. 當你準備好了時,為每個設備分類打包你的腳本和樣式表。
5. 如果客戶端重定向有性能問題,放棄device.js,并換到服務器端做UA檢測。
原文鏈接:http://www.itivy.com/iphone/archive/2012/5/18/634729762320220086.html
【編輯推薦】
【責任編輯:張偉 TEL:(010)68476606】