混合應用(hybird app)
在幾年前便進入大衆視野,近來更是愈加風生水起,深受人民羣衆的喜好。javascript
混合應用(hybird app)
顧名思義,即是將web app與native app混合在一塊兒,既享受html快速開發、快速版本迭代帶來的便利,也能使用原生app調用系統接口和第三方SDK的強大擴展能力。html
如同茴字有幾種寫法
通常,構建混合應用也有不一樣的方式。其中一種是主要使用靜態html,用 phonegap
或 cordova
加殼的方式打包成app。另外一種則是小部分webview直接引入服務端渲染的html,其餘功能都是原生app開發。
其中前一種方式最爲出名的解決方案即是使用 angular.js
+ cordova
的 ionic,而使用後一種方式的app則數不勝數。
可是不管使用哪種方式,都面臨一個問題,html和app的交互。html本身不會動起來,本文將淺談javascript如何交互app和html。html5
常見的app和html交互有 使用url
和 互相調用方法
兩種方式。使用url
這種方式比較簡單,經過 location.href = 'url'
,便可將方法和參數傳遞給app,可是沒法傳遞複雜的數據。互相調用方法
這種方式則較爲複雜,除了須要app端寫好調用的方法注入到 window
對象以外,還須要JavaScript暴露方法給app使用。以常見的評論交互爲例:java
// 點擊「發表評論」,js須要調用app的評論框 $('.js-comment').click(function(){ window.appMethod.comment(); }); // app端在用戶點擊「發送」按鈕時,再調用javascript的插入評論方法(我不會app開發,如下是僞代碼) function comment(){ TEXTAREA.OPEN(); } SUBMIT_BUTTON.CLICK(function(){ NSString * result = [self.webView stringByEvaluatingJavaScriptFromString:@"window.jsMethod.comment()"]; })
其中 window.appMethod
這個方法,是一個從 iOS 和 android 方法中提取而來的方法,根據手機系統不一樣,使用不一樣策略,例如:jquery
var window.appMethod = null; var androidMethod = { comment: function(){ window.android.comment(); } }; var iOSMethod = { comment: function(){ location.href = 'ios://comment?' } }; window.appMethod = iOS_DEVICE ? iOSMethod : androidMethod;
相比方法的注入點,策略處理,方法的調用時機更爲重要。在js中調用一個不存在方法,會發生錯誤從而致使代碼沒法繼續向下執行。
好比進入頁面時,app須要告訴html一些登陸信息,以初始化點贊,收藏等組件。若是由app直接調用js方法去通知,那麼極可能頁面還沒加載完,而發生上面提到的錯誤。
因此好的時機是讓js主動去向app發起請求,示例:android
// 不和諧:app直接通知js更新用戶登陸狀態,可能會發生錯誤 eval('window.jsMethod.setUser();') // 和諧:js主動去向app發起請求 $(function(){ window.appMethod.getUser(); }) // app端在接收到getUser方法後,調用js方法(我不會app開發,如下是僞代碼) function getUser(){ // 獲取user狀態,而後執行 NSString * result = [self.webView stringByEvaluatingJavaScriptFromString:@"window.jsMethod.setUser()"]; }
以上的示例中的方法並無進行參數傳遞,是爲了留到這裏。
相比JavaScript,在android和iOS方法中傳遞參數顯得極爲嚴格,除了要指定參數個數,還要指定參數類型。
雖然能夠經過數組的方式進行不定個數參數的傳遞,可是指定參數類型仍是挺煩人的。因此建議始終使用 String
類型做爲參數進行傳遞,複雜的json格式參數使用 JSON.stringify
。使用url傳遞則須要對參數進行 encode 編碼。
以上面的發表評論爲例:ios
# 本段代碼使用了jquery // js給app傳參 var androidMethod = { comment: function(params){ window.android.comment( JSON.stringify(params) ); } }; var iOSMethod = { comment: function(params){ location.href = 'ios://comment?'+$.param(params) } }; ... ... $('.js-comment').click(function(){ var params = { "user_id": 30, "article_id": 958, "article_type": "news" }; window.appMethod.comment(params); }); // app給js傳參 SUBMIT_BUTTON.CLICK(function(){ var params = { "comment_id": 5484, "comment_content": "我不會寫app,姑且用js寫僞代碼" }; NSString * result = [self.webView stringByEvaluatingJavaScriptFromString:@"window.jsMethod.comment( JSON.stringify(params) )"]; })
這裏的方法監聽指的是app對js方法的單向監聽。
由於須要app監聽的js方法,都是顯示的調用了app方法,或是跳轉到了一個url。調用app的方法自不待言,url的監聽卻有多種。
一種是a連接的 http
GET 請求的監聽,多見於 下一篇文章
, 相關文章
等跳轉頁面的方法。通常來講不用帶參數。還有一種是自定義的 schema
監聽,使用這種方式通常是不帶或帶較少的參數,好比 myiOS://mymethod?
。git
把資源加載放到交互裏面,我也不知道合不合適。對於 第一種混合方式 來講,能夠把更多的靜態資源放到本地,而後經過app接口加載。對於第二種,更多的仍是從服務端渲染並加載資源。
對於一些交互類的數據,而非資源,既能夠選擇存放在瀏覽器的localStorge中,也能夠選擇存放於app本地文件,這取決於哪一方進行操做運算了。github
html的移動端調試時很困難的,嵌入app的html調試更是難上加難。由於js和app的方法相互調用,任何一方出錯,都會致使程序不按套路運行。
除了仔細的約定兩端的方法和檢查代碼的錯誤外,還須要一個強力的工具。在這裏推薦使用 vConsole ,能夠比較直觀的定位到錯誤。web
vConsole 截圖
html在app中的兼容性取決於app內嵌瀏覽器內核。iOS系統默認的瀏覽器是safari,而andriod系統默認的瀏覽器則五花八門。
若是選擇系統默認瀏覽器做爲內嵌瀏覽器的話,ios通常兼容性較好,能取得和PC端一致的效果。android機型則會比較悲劇,使用 crosswalk方案 或許是個正確的選擇。
在內嵌瀏覽器中,html5的某些特性默認是關閉的,好比 localStorge
, 須要app端手動去開啓。因此在開發中必定要作好可用性檢測,減小出現bug的概率。
當html做爲webview的局部視圖被加載時,因爲app雖然能夠獲取到頁面加載後的高度,可是沒法獲取動態改變後的高度,使得局部滾動失效。因此在做爲局部視圖加載時,若是須要頁面高度會根據好比評論,動畫效果而發生改變的話,須要及時通知app更新webview高度。