混合應用中的javascript實踐

混合應用(hybird app) 在幾年前便進入大衆視野,近來更是愈加風生水起,深受人民羣衆的喜好。javascript

概念

什麼是混合應用

混合應用(hybird app) 顧名思義,即是將web app與native app混合在一塊兒,既享受html快速開發、快速版本迭代帶來的便利,也能使用原生app調用系統接口和第三方SDK的強大擴展能力。html

混合方式

如同茴字有幾種寫法通常,構建混合應用也有不一樣的方式。其中一種是主要使用靜態html,用 phonegapcordova 加殼的方式打包成app。另外一種則是小部分webview直接引入服務端渲染的html,其餘功能都是原生app開發。
其中前一種方式最爲出名的解決方案即是使用 angular.js + cordovaionic,而使用後一種方式的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 截圖

vConsole

其餘

兼容性

html在app中的兼容性取決於app內嵌瀏覽器內核。iOS系統默認的瀏覽器是safari,而andriod系統默認的瀏覽器則五花八門。

若是選擇系統默認瀏覽器做爲內嵌瀏覽器的話,ios通常兼容性較好,能取得和PC端一致的效果。android機型則會比較悲劇,使用 crosswalk方案 或許是個正確的選擇。

特性啓用

在內嵌瀏覽器中,html5的某些特性默認是關閉的,好比 localStorge , 須要app端手動去開啓。因此在開發中必定要作好可用性檢測,減小出現bug的概率。

局部視圖

當html做爲webview的局部視圖被加載時,因爲app雖然能夠獲取到頁面加載後的高度,可是沒法獲取動態改變後的高度,使得局部滾動失效。因此在做爲局部視圖加載時,若是須要頁面高度會根據好比評論,動畫效果而發生改變的話,須要及時通知app更新webview高度。

相關文章
相關標籤/搜索