混合开发篇-原生与H5交互

## 混合开发

DCLOUD实现混合开发的方式,微信公众号的二次开发,微信小程序

### 现有的NativeAPP、WebAPP、HybridAPP的区别

APP:application应用程序,一般指移动端的应用。

1. NativeAPP:

由Andriod、IOS开发人员开发;使用的语言是:xml+java;xml+(Objective-C/swift);

对网络的依赖性不强(在没有网络的情况下也能使用部分功能);流畅度较高;能调用设备的原生功能;

应用需要下载安装,使用成本高;更新维护成本也较高;开发成本也比较高;

2. WebAPP:(移动设备通过浏览器访问的移动端web应用)

有web前端开发人员开发;使用的语言是:html+css+js;

不需要下载安装,使用成本低,更新成本低,因为H5webapp都是跨平台、跨浏览器的,所以开发成本较低,兼容性好;

不能调用设备原生功能;流畅度较native稍稍差一点;对网络依赖性较高(正在用离线缓存的技术在解决)

3. HybridAPP:混合开发app 、混合app、小杂种app 介于NativeAPP和WebAPP之间的应用,集合了原生用户良好的用户交互体验和webapp跨平台开发的优势

原生应用有一个东西叫webview,可以承载web页面

分类:1. 原生主导(最流行) 2.H5主导

原生主导:

在某些地方通过webview载入web页面作为界面展示使用,一般展示性的,更新较频繁的,用户交互较少的,例如详情页、列表等页面都可以这么做

检验方式:

1. 通过长按看是否出现选中内容可以复制粘贴的使用,如果可以说明是web页面,但是web页面可以通过一些设置来阻止这个事情。

2. 在Android的某些机器里,开发者视图,没有被大量的线包裹的界面就是web页面。

对于web前端来说,需要写某些页面来嵌入到Android和ios中,需要注意的是:

1. 需要判断机型后进行不同操作,使用navigator上的userAgent、appVersion等属性来做判断

2. 与原生进行交互。

## 前言

我们知道混合开发的模式现在主要分为两种,H5工程师利用某些工具如DCLOUD产品、codorva+phonegap等等来开发一个外嵌native壳子的混合app

还有就是应用比较广泛的,有native开发工程师和H5工程师一起写作开发的应用,在native的webview里嵌入H5页面,当然只是部分界面这么做,这样做的好处就是效率高,开发成本和维护成本都比较低,较为轻量,但是有一个问题不可避免的会出现,就是js和native的交互

native与js交互部分等详细内容请移步这里:

[简书资源](http://www.jianshu.com/p/d19689e0ed83)

[掘金资源](https://juejin.im/post/599a58f6f265da247b4e756b)

---

### Native(Objective-C或Swift)调用Javascript方法

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

```

// Swift

webview.stringByEvaluatingJavaScriptFromString("Math.random()")

// OC

[webView stringByEvaluatingJavaScriptFromString:@"Math.random();"];

```

从上面代码可以看出它其实就是调用了window下的一个对象,如果我们要让native来调用我们js写的方法,那这个方法就要在window下能访问到。但从全局考虑,我们只要暴露一个对象如JSBridge对native调用就好了,所以在这里可以对native的代码做一个简单的封装:

```

//下面为伪代码

webview.setDataToJs(somedata);

webview.setDataToJs = function(data) {

webview.stringByEvaluatingJavaScriptFromString("JSBridge.trigger(event, data)")

}

```

另外:==在android中,native与js的通讯方式与ios类似==

#### 2.在iOS 7之后,apple添加了一个新的库JavaScriptCore

```

JSContext *context = [self.webView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"];

NSString *textJS = @"showAlert('这里是JS中alert弹出的message')";

[context evaluateScript:textJS];

```

---

## Javascript -> OC/Swift

Javascript调用Native,并没有现成的API可以直接拿来用,而是需要间接地通过一些方法来实现。UIWebView有个特性:在UIWebView内发起的所有网络请求,都可以通过delegate函数在Native层得到通知。这样,我们就可以在UIWebView内发起一个自定义的网络请求,通常是这样的格式:

```

jsbridge://methodName?param1=value1¶m2=value2

```

发起这样一个网络请求有两种方式:

1. 通过localtion.href;

2. 通过iframe方式;

通过location.href有个问题,就是如果我们连续多次修改window.location.href的值,在Native层只能接收到最后一次请求,前面的请求都会被忽略掉。

使用iframe方式,以唤起Native APP的分享组件为例,简单的封闭如下:

```

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);

```

#### 2.还有一种方式就是使用JavaScriptCore

定义好JS需要调用的方法,例如JS要调用share方法:

则可以在UIWebView加载url完成后,在其代理方法中添加要调用的share方法

这样的话web页面中就可以直接使用到这个方法:

```

function secondClick() {

share('分享的标题','分享的内容','图片地址');

}

...

Click Me!

```

---

### javascript调用native Android方式

目前在android中有三种调用native的方式:

#### 1.通过schema方式,使用shouldOverrideUrlLoading方法对url协议进行解析。这种js的调用方式与ios的一样,使用iframe来调用native代码。

#### 2.通过在webview页面里直接注入原生js代码方式,使用addJavascriptInterface方法来实现。

在android里实现如下:

```

class JSInterface {

@JavascriptInterface //注意这个代码一定要加上

public String getUserData() {

return "UserData";

}

}

webView.addJavascriptInterface(new JSInterface(), "AndroidJS");

```

上面的代码就是在页面的window对象里注入了AndroidJS对象。在js里可以直接调用

```

alert(AndroidJS.getUserData()) //UserDate

```

#### 3.使用prompt,console.log,alert方式,这三个方法对js里是属性原生的,在android webview这一层是可以重写这三个方法的。一般我们使用prompt,因为这个在js里使用的不多,用来和native通讯副作用比较少。

```

class YouzanWebChromeClient extends WebChromeClient {

@Override

public boolean onJsPrompt(WebView view, String url, String message, String defaultValue, JsPromptResult result) {

// 这里就可以对js的prompt进行处理,通过result返回结果

}

@Override

public boolean onConsoleMessage(ConsoleMessage consoleMessage) {

}

@Override

public boolean onJsAlert(WebView view, String url, String message, JsResult result) {

}

}

```

---

## 总结

#### OC/SWIFT调用js

直接用一些方法执行我们js中的一些语句,也就是说,我们最好定义一些对象,上面放着一些方法准备被native调用,当然也就可以在这些方法里传点参数啥的给咱们了

#### js调用iframe

咱们可以整一个请求发出去,这个请求呢会被native给拦截到,他就指的啥意思了

比如,我们可以通过 location.href=A://b=1&c=2&d=3 当然这里的A、b、c、d都要商量好,bcd就是传参数

但是location.href只能发一次,所以我们可以用iframe去发,发完了给iframe干掉就可以了

#### android 调用 js 和oc、swift一样,这里就不说了

#### js调用Android

1.也跟调用ios一样,搞个请求,用个iframe

2.Android能想办法给咱的window对象上挂个东西,比如JSBridge啥的然后咱直接调这个玩意的方法就行了

3.他们能把咱的prompt、console.log、alert给重写咯,也就是说咱用alert已经不能弹出了,反而能给Android传参数了,但是一般不会重写alert,重写的都是不怎么用的prompt

你可能感兴趣的:(总结小计,javascript,webview,android,ios,html5)