利用原生+h5模式開發app也有一段時間了,寫篇文章來介紹一下如今的開發模式。因爲剛剛畢業半年接觸前端也沒有多久,不少也是本身摸索出來的,不足之處還請多多指正。javascript
首先爲了可以更加快捷高效的開發,咱們當時決定使用把js的資源包直接放在本地讓webview去加載的模式,而不是放在服務端去讓webview去加載。html
那就存在了一個問題,每次開發完js後,都要把編譯後的文件手動的copy到android和ios的資源目錄裏,那豈不是很是的麻煩。正好git有子模塊的概念,可以很好的解決這個問題。前端
先介紹一下git的子模塊,子模塊就是爲了解決能單獨處理多個項目,並擁有共同的模塊的問題。首先這多個項目每一個項目都是一個倉庫,而後子模塊也是一個單獨的倉庫,這個單獨的倉庫可以被多個項目共享。這樣的話咱們就能夠把h5編譯後的文件做爲一個子模塊,讓h五、android、ios都填加這個子模塊。就能夠只需在h5代碼更新後,編譯一下,而後將子模塊推送到遠端,android和ios直接更新一會兒模塊就能夠實現實時的更新h5的資源包了,而不用咱們每次更新了h5的代碼,還要每次去手動的複製粘貼了。vue
這裏用個圖來表示一下java
交互處理雖然網上一堆的資料介紹,不過仍是在此記錄一下。android
js與android webview的交互ios
android 加載本地的h5資源git
//首先webview啓用js支持
webView.getSettings().setJavaScriptEnabled(true);
// 而後assets目錄下面的加載html (android 這裏將h5編譯後的資源包放在了assets/h5目錄下)
webView.loadUrl("file:///android_asset/h5/index.html");
//webview須要添加js的接口協議 此處的phone用來指定js的實例名稱
webView.addJavascriptInterface(MainActivity.this, "phone");
複製代碼
android調用js方法github
js方法web
//前端採用了vue.js 發現只有將方法掛載在全局的window上才能被調用,不知道還有沒有別的方法
window.hello = function () {
}
window.helloParam = function (value) {
}
複製代碼
android 調用js方法
//調用無參的js hello方法
webView.loadUrl("javascript:hello()");
//調用有參的js helloParam方法
String hello = "hello!!!";
webView.loadUrl("javascript:helloParam('" + hello + "')");
//注意 如何參數是boolean或者 int型時 須要把單引號去掉
webView.loadUrl("javascript:helloParam(" + true + ")");
複製代碼
js調用android方法
android 方法
//在方法上添加 @JavascriptInterface就能被調用了 可是須要注意 涉及ui處理的部分須要回到主線程操做
//無參無返回方法
@JavascriptInterface
public void startFunction() {
runOnUiThread(new Runnable() {
@Override
public void run() {
Toast.makeText(MainActivity.this, "hello!", Toast.LENGTH_SHORT).show();
}
});
}
//無參有返回方法
@JavascriptInterface
public void startFunction() {
return "hello!"
}
//有參有返回方法 建議參數爲某個模型時都轉換成jsonString來傳值
@JavascriptInterface
public void startFunction(final String text) {
runOnUiThread(new Runnable() {
@Override
public void run() {
Toast.makeText(MainActivity.this, text, Toast.LENGTH_SHORT).show();
}
});
return "hello!"
}
複製代碼
js調用android方法
//此處的phone須要和移動端定的js的實例名稱保持一致
window.phone.startFunction()
window.phone.startFunction('hello!!')
複製代碼
js與ios UIWebview的交互
ios UIWebview加載本地的h5資源
//首先在ios的項目目錄下新建一個h5的文件用來存放h5的資源包,而後在xcode中經過Add Files to 「ProjectName」的方式導入進來
//加載h5目錄下的index.html
let path = Bundle.main.path(forResource: "index", ofType:"html", inDirectory:"h5")
let url = URL(fileURLWithPath:path!)
let request = URLRequest(url:url)
let jsContext = mWebview.value(forKeyPath: "documentView.webView.mainFrame.javaScriptContext") as? JSContext
//此處的phone用來指定js的實例名稱 JavaScriptMethod在下文中實現
jsContext?.setObject(JavaScriptMethod(holderController:self), forKeyedSubscript: "phone" as NSCopying & NSObjectProtocol)
mWebview.loadRequest(request)
複製代碼
ios UIWebview調用js方法
self.mWebview.stringByEvaluatingJavaScript(from: "helloParam('Hello Js!')")
複製代碼
js調用 ios UIWebview方法
ios UIWebview方法
@objc protocol JavaScriptMethodProtocol: JSExport {
//無參無返回方法
func startFunction()
//無參有返回方法
func startFunction()->String
//有參又返回方法 注意:此處不要漏寫下滑線
func startFunction(_ param: String)
}
class JavaScriptMethod : NSObject, JavaScriptMethodProtocol {
private var holderController: ViewController?
init(holderController:ViewController) {
super.init()
self.holderController = holderController
}
func startFunction() {
NSLog("hello!");
}
func startFunction() -> String{
return "hello!"
}
func startFunction(_ param: String) {
NSLog(param);
}
}
複製代碼
js調用
//此處的phone須要和移動端定的js的實例名稱保持一致
window.phone.startFunction()
window.phone.startFunction('hello!!')
複製代碼
首先在github上新建一個子模塊的倉庫
爲h5,ios,android的項目都添加這個子模塊(h5將編譯文件目錄做爲子模塊的路徑)
git submodule add <repository>子模塊倉庫地址 <path>子模塊的路徑
複製代碼
h5開發完後,將編譯後的文件提交的子模塊倉庫的遠端 可使用命令方式提交或者使用SourceTree等工具來輔助提交
//例如編譯後文件在dist目錄下
cd dist
git add --all
git commit -m"h5更新"
git push
複製代碼
android和ios本地更新子模塊, 而後推送至遠端 或者使用SourceTree等工具。。。
git submodule foreach git pull origin master
git add --all
git commit -m"h5更新"
git push
複製代碼
jenkins配置自動更新子模塊
看完上述操做有些朋友可能會以爲有些繁瑣。每次h5更新,我都要在android和ios上去更新子模塊,那豈不是很麻煩。好比我本地原生代碼沒有任何的改動,可是h5的子模塊更新了,還要在android和ios上都去更新一下。那麼在jenkins上配置以下命令,就能夠保證每次編譯出來的安裝包,子模塊都是最新的了
git submodule init
git submodule update
git submodule foreach git pull origin master
複製代碼
其實混合App的開發場景應該並很少見,咱們公司也是在須要開發較爲複雜的電商首頁,和在須要使用大量的圖表(爲了android和ios樣式統一,選用了echarts圖表庫)的場景時才使用了這樣的模式開發。