美文网首页
H5 与Native的交互方案

H5 与Native的交互方案

作者: 风之化身呀 | 来源:发表于2017-11-11 20:35 被阅读948次

    1、前言

    App里基本都少不了H5页面,因此JS与Native之间的通信不可避免,最近留意了一些方案,做下总结。

    2、iOS与H5通信

    iOS有两种webview,ios8以上推出了WKWebView,低于ios8用的是UIWebView,WKWebView性能上优于UIWebView

    2.1 、iOS调用H5

    Native调用Javascript语言,是通过UIWebView组件的stringByEvaluatingJavaScriptFromString方法来实现的,该方法返回js脚本的执行结果。

    // Swift
    webview.stringByEvaluatingJavaScriptFromString("Math.random()")
    // OC
    [webView stringByEvaluatingJavaScriptFromString:@"Math.random();"];
    

    双方只需要约定好JS端函数名称及参数

    2.2、 H5调用iOS

    JS调用Native,并没有现成的API可以使用,需要借助iframe来实现。原理是在UIWebView内发起的所有网络请求,都可以通过delegate函数在Native层得到通知。所以只需要劫持该UIWebView内的所有请求(通常是这样的格式:jsbridge://methodName?param1=value1&param2=value2),然后在UIWebView的delegate函数中,只要发现是jsbridge://开头的地址,就不进行内容的加载,转而执行相应的调用逻辑:

    // JS 端关键代码
    var url = 'jsbridge://doAction?title=分享标题&desc=分享描述&link=http%3A%2F%2Fwww.baidu.com';
    var iframe = document.createElement('iframe');
    iframe.style.width = '1px';
    iframe.style.height = '1px';
    iframe.style.display = 'none';
    iframe.src = url;
    document.body.appendChild(iframe);
    setTimeout(function() {
        iframe.remove();
    }, 100);
    
    // OC端关键代码
    func webView(webView: UIWebView, shouldStartLoadWithRequest request: NSURLRequest, navigationType: UIWebViewNavigationType) -> Bool {
            print("shouldStartLoadWithRequest")
            let url = request.URL
            let scheme = url?.scheme
            let method = url?.host
            let query = url?.query
    
            if url != nil && scheme == "jsbridge" {
                print("scheme == \(scheme)")
                print("method == \(method)")
                print("query == \(query)")
    
                switch method! {
                    case "getData":
                        self.getData()
                    case "putData":
                        self.putData()
                    case "gotoWebview":
                        self.gotoWebview()
                    case "gotoNative":
                        self.gotoNative()
                    case "doAction":
                        self.doAction()
                    case "configNative":
                        self.configNative()
                    default:
                        print("default")
                }
    
                return false
            } else {
                return true
            }
        }
    

    3、Android与H5通信

    3.1 、Android调用H5

    在android里是使用webview的loadUrl进行调用的

    // 调用js中的JSBridge.trigger方法
    webView.loadUrl("javascript:JSBridge.trigger('webviewReady')");
    

    3.2、 H5调用Android

    有两种比较好的方式:

    • 和iOS一样,通过iframe(Android端通过shouldOverrideUrlLoading方法对url协议进行解析)
    • 通过在webview页面里直接注入原生js代码方式,使用addJavascriptInterface方法来实现。
      在android里实现如下:
    class JSInterface {
        @JavascriptInterface //注意这个代码一定要加上
        public String getUserData() {
            return "UserData";
        }
    }
    webView.addJavascriptInterface(new JSInterface(), "AndroidJS");  //window对象里注入了AndroidJS对象
    

    JS端可以直接调用:alert(AndroidJS.getUserData()) //UserDate

    4、iOS与H5通信的其它方案

    基于 callHandler 和 registerHandler的方式,比较干净

    • JS调用Native
            setupWebViewJavascriptBridge(e => {
            e.callHandler("getHttpHeader", {}, function(data) {   //getHttpHeader方法在ios端定义好
                fn(data);
            })
        })
    
    • Native调用JS
    setupWebViewJavascriptBridge(e => {
        e.registerHandler("navBarButtonClicked", (data, responseCallback) => { //H5端注册navBarButtonClicked
            if (data == 'mine') {
                ...
            }
        })
    })
    
    //
    const setupWebViewJavascriptBridge = e => {
        if (window.WebViewJavascriptBridge)
            return e(WebViewJavascriptBridge);
        if (window.WVJBCallbacks)
            return window.WVJBCallbacks.push(e);
        window.WVJBCallbacks = [e];
        var t = document.createElement("iframe");
        t.style.display = "none";
        t.src = WVJBIframeSrc();
        document.documentElement.appendChild(t);
        setTimeout(function() {
            document.documentElement.removeChild(t)
        }, 0)
    };
    

    5、小结

    • iOS调H5(stringByEvaluatingJavaScriptFromString),H5调iOS(iframe,schema协议)
    • Android调H5(webView.loadUrl()),H5调Android(1、iframe;2、addJavascriptInterface)
    • 从可维护性上看,H5端都用iframe方式调用iOS&Android最好
    • 从实际操作上看,H5端需要维护一个专门用于和Native端通信的js库(封装iframe及一些方法定义),俗称SDK;
      Native端需要各自与H5端定义的函数对接。

    6、参考文档

    1、Web 与 App 数据交互原理和实现
    2、WK 与 JS 的那些事
    3、H5 与 Native 交互之 JSBridge 技术
    4、WebView 开车指南之最全实用案例

    相关文章

      网友评论

          本文标题:H5 与Native的交互方案

          本文链接:https://www.haomeiwen.com/subject/odcgmxtx.html