混合開發模式介紹

1. 開發模式介紹

利用原生+h5模式開發app也有一段時間了,寫篇文章來介紹一下如今的開發模式。因爲剛剛畢業半年接觸前端也沒有多久,不少也是本身摸索出來的,不足之處還請多多指正。javascript

首先爲了可以更加快捷高效的開發,咱們當時決定使用把js的資源包直接放在本地讓webview去加載的模式,而不是放在服務端去讓webview去加載。html

那就存在了一個問題,每次開發完js後,都要把編譯後的文件手動的copy到android和ios的資源目錄裏,那豈不是很是的麻煩。正好git有子模塊的概念,可以很好的解決這個問題。前端

先介紹一下git的子模塊,子模塊就是爲了解決能單獨處理多個項目,並擁有共同的模塊的問題。首先這多個項目每一個項目都是一個倉庫,而後子模塊也是一個單獨的倉庫,這個單獨的倉庫可以被多個項目共享。這樣的話咱們就能夠把h5編譯後的文件做爲一個子模塊,讓h五、android、ios都填加這個子模塊。就能夠只需在h5代碼更新後,編譯一下,而後將子模塊推送到遠端,android和ios直接更新一會兒模塊就能夠實現實時的更新h5的資源包了,而不用咱們每次更新了h5的代碼,還要每次去手動的複製粘貼了。vue

這裏用個圖來表示一下java

2. js與原生交互處理

交互處理雖然網上一堆的資料介紹,不過仍是在此記錄一下。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!!')
    複製代碼

3. 子模塊詳細操做說明

  1. 首先在github上新建一個子模塊的倉庫

  2. 爲h5,ios,android的項目都添加這個子模塊(h5將編譯文件目錄做爲子模塊的路徑)

    git submodule add <repository>子模塊倉庫地址 <path>子模塊的路徑
    複製代碼
  3. h5開發完後,將編譯後的文件提交的子模塊倉庫的遠端 可使用命令方式提交或者使用SourceTree等工具來輔助提交

    //例如編譯後文件在dist目錄下
    cd dist 
    git add --all
    git commit -m"h5更新"
    git push
    複製代碼
  4. android和ios本地更新子模塊, 而後推送至遠端 或者使用SourceTree等工具。。。

    git submodule foreach git pull origin master
    git add --all
    git commit -m"h5更新"
    git push
    複製代碼
  5. 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圖表庫)的場景時才使用了這樣的模式開發。

相關文章
相關標籤/搜索