僅僅利用media query適配樣式是遠遠不夠的,並無考慮觸屏下的行爲和特有的內容組織方式的不一樣。簡單在桌面版基礎上疊加mobile版的代碼,會帶來請求增多、流量、性能、代碼冗餘等諸多方面問題。有統計說86%的手機站看起來small其實體積比桌面版還大。css
咱們此次充分發揮「響應」的靈活性,實現one web。html
1. 響應性的模塊
本來網站的模塊化程度越高越便於作響應性開發。一個page例如是這樣組織的:
<%include file=」path/mod1.html」 args=」data=data」 />
<%include file=」path/mod2.html」 args=」data=data」 />
若是在手機下訪問,模板系統在生成這個頁面時,會在path/下找mobile.mod1.html,有則加之,不然加mod1.html。也就是說在同一目錄下,會存在多個版本的模塊,當前只有2種:mod1.html(桌面版),mobile.mod1.html(mobile版)node
響應部分的代碼,跟主站代碼是放在一塊兒的,這樣更便於維護。一個頁面模板的結構是這樣的:jquery
page1.html:android
<%inherit file=」/base.html」 />ios
<%def name=」main」>git
桌面版主要內容github
<%include file=」path/mod1.html」 args=」data=data」 />web
</%def>
<%def name=」sidebar」>
桌面版邊欄內容
</%def>
<%def name=」mobile_main」>
<%block filter=」collect_css」>
mobile版css
</%block>
mobile版主要內容。若是能夠複用,直接調${self.main()}
不少狀況下內容是不一樣的,好比去掉沒必要要的模塊。
</%def>
<%def name=」mobile_sidebar」>
mobile版底部內容
</%def>
這意味能夠同時開發/維護兩個版本。(一樣,設計師在設計一個頁面,也須要秉承mobile first的原則)
在同一目錄、同一文件維護比分佈在不一樣的倉庫中要方便的多。
2. 響應性的css/js
mobile版的變化很大,在樣式上並非桌面版css+mobile版css的關係。這得益於咱們以前對靜態文件管理系統的改造。傳統的css的組織方式是集中式的,集中在幾個通用文件中,形如base.css + product.css。而咱們如今的方式是base.css + mod_1.css(inline) + mod_2.css(inline) + mod_3.css(inline) … 是按需組合的形式。
這樣,加上設備判斷後就能夠輕易變成:
mobile.base.css + mobile.mod_1.css(inline) + mobile.mod_2.css(inline) + mobile.mod_3.css(inline) …
css/js文件跟模板同樣,在同一目錄下分別有桌面版和mobile版。根據訪問端的狀況,自動適配、按需組合。這樣能夠獲得一個更優化的mobile站。
3. 加強觸屏行爲和兼容桌面事件
前者是指附加觸屏上特有的事件:touchstart/touchmove/touchend以及手勢swip/pinch/rotate/shake。這個不是難點。
mobile瀏覽器和桌面瀏覽器的事件模型有明顯差別,爲了徹底複用桌面版的各類js組件,首要問題是設法兼容桌面事件(click和mouse事件)。
mobile上的click和mouse事件有幾個須要注意的地方:
a. click和mouse事件不會發生在不可點擊的元素上,意味綁在document上的事件代理徹底失效
b. mouse事件是發生在手指離開屏幕後,且順序是mouseover > mousemove > mousedown > mouseup
c. click事件最後觸發。從手指離開屏幕起,有約300多毫秒延遲,並且有可能不會被觸發
見下圖:
「If the user taps a clickable element, events arrive in this order: mouseover, mousemove, mousedown, mouseup, and click. The mouseout event occurs only if the user taps on another clickable item. Also, if the contents of the page changes on the mousemove event, no subsequent events in the sequence are sent.」(出處)
android/ios不支持beforeunload事件,對unload事件的支持有些怪異,須要用pageshow/pagehide事件替代。
以上事件的差別都是要盡力消除的。解決思路是利用jQuery的special event機制覆蓋掉本來的事件綁定。即:node.click(fn),mobile上轉向node.touchend(fn) 。實現的代碼:https://gist.github.com/3358036
4. 優化和用戶體驗
a.去掉了apple-mobile-web-app-capable聲明。單頁應用要加上,用響應式開發的加上這句體驗反而很差,跳轉的連接會彈出窗口打開。
<meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1,user-scalable=no">
<meta name="format-detection" content="telephone=no"/>
## <meta name="apple-mobile-web-app-capable" content="yes">
b. 「If the user taps a nonclickable element, no events are generated.」(引自Apple Dev Center),因此:
body {
cursor:pointer;
}
c. 設定內容中圖片的最大寬:
.topic-content img {
max-width:100%;
}
d. 加載提示,感受像異步加載。
e. application cache自己是爲web app設計的,在響應式開發中的應用是不一樣的。
把大文件在手機端cache起來:
CACHE MANIFEST
# version 0.0.1
CACHE:
${static('/js/jquery.min.js')}
${static('/js/do.js')}
${static('/css/mobile/base.css')}
${image_url('/pics/icon/dou.png')}
${static('/css/ui/dialog.css')}
${static('/js/ui/dialog.js')}
${static('/js/mobile/jquery.mobile.events.js')}
這個文件是動態生成的,好處是當文件更新後,文件名中的簽名會跟着變,也就會觸發手機端app cache的更新。
判斷cache更新:
if (window.applicationCache) {
window.applicationCache.addEventListener('updateready',function(){
window.applicationCache.swapCache();
}, false);
}
爲了不動態頁面被cache,在一個隱藏的iframe裏指定它。(更改,還須要進一步測試)
f. mobile上的UI庫,比桌面版更有必要。
5. 調試和監測
用了兩個工具adobe shadow和自帶的tcpdump,對android/ios均適用。
a. adobe shadow 出了一段時間了。原來的問題是它要走adobe的weinre server,慢!終於最新版4已經能夠指定本地的weinre server了。怎麼啓用本地weinre server是另外話題本身去搜吧,我是用jar啓動的,做者網站提供各類版本:http://people.apache.org/~pmuellr/weinre/builds/1.x/
>java -jar ~/weinre-jar/weinre.jar –boundHost 10.0.2.48 (ifconfig查具體ip是什麼)
weinre server啓動參數:
–httpPort [portNumber] | 改變HTTP服務器的端口號 | 8080 |
–boundHost [hostname | ip address | -all-] | 改變主機名。若是使用默認的localhost,將沒法從另外一臺機器訪問該服務器 | localhost |
–verbose [true | false] | 記錄標準輸出行爲 | false |
–debug [true | false] | 詳細的操做日誌輸出到標準輸出 | false |
–deathTimeout [seconds] | 指定超時 | 3 |
安裝shadow,同時手機上安裝shadow client。
指定本地server:
手機打開shadow client直接找ip。shadow其實就是對weinre包裝了一層,它的inspector其實就是weinre調web inspector調試。
b. 用tcpdump監測http請求(參考這裏)。步驟:
step 1: 建一個wifi熱點
step 2: 用tcpdump命令捕獲tcp的traffic,命令:
sudo tcpdump -i en1 -n -s 0 -w group.pcap tcp or port 53
(參考tcpdump用法http://www.tcpdump.org/tcpdump_man.html)
step 3: 手機聯上熱點,打開網站(先清cache)
step 4: Ctrl+c停掉tcpdump,log保存到指定的group.pcap文件中。pcap(packet capture)
step 5: pcap轉成har文件瀏覽,http://pcapperf.appspot.com 或導入到charles裏查看也很方便,分別看下圖:
c. 在線工具:mobitest.akamai.com (說是開源了)