因此,基于网络环境和渲染性能的影响,在设计H5页面时,应注意以下几点:
在做Hybrid架构设计之前需要分清Native与前端的界限,首先Native提供的是一宿主环境,要合理的利用Native提供的能力,要实现通用的Hybrid平台架构,站在前端视角,我认为需要考虑以下核心设计问题。
Hybrid架构设计第一个要考虑的问题是如何设计与前端的交互,如果这块设计的不好会对后续开发、前端框架维护造成深远的影响,并且这种影响往往是不可逆的,所以这里需要前端与Native好好配合,提供通用的接口,比如:
①NativeUI组件,header组件、消息类组件
②通讯录、系统、设备信息读取接口
③H5与Native的互相跳转,比如H5如何跳到一个Native页面,H5如何新开Webview做动画跳到另一个H5页面
Native首先需要考虑如何访问H5资源,做到既能以file的方式访问Native内部资源,又能使用url的方式访问线上资源;需要提供前端资源增量替换机制,以摆脱APP迭代发版问题,避免用户升级APP。这里就会涉及到静态资源在APP中的存放策略,更新策略的设计,复杂的话还会涉及到服务器端的支持。
账号系统是重要并且无法避免的,Native需要设计良好安全的身份验证机制,保证这块对业务开发者足够透明,打通账户信息。
Hybrid交互有两种:1、native主动调用前端js方法主动与前端通信2、H5主动与native通信是通过urlschema方式进行的,首先要和native约定好通信的schema如:wubacst然后根据Android和iOS不同的通信方式来分别约定其中Android是在通信之前先创建一个iframe通过iframe把拼接好的url请求发送到native或者通过拦截prompt中的消息来和前端通信iOS使用了iOS8以上的wkwebview中的messageHandlers的postMessage方法直接把url请求发送到nativenative接收到前端发送的请求解析之后通过回调函数来通知前端
两者通信的桥梁都是webview
iOS基于WebKit框架的中的WKWebView+WKScriptMessageHandler实现JS与OC之间互相通信。整体交互过程分为三步:第一:通过-(void)addScriptMessageHandler:(id
将UIWebViewDelegate与UIWebView拆分成了14类与3个协议,包含该更细节功能的实现
WKWebView:
类似于JOSNP跨域原理APP在安装之后会注册私有协议到OS,浏览器自身不能识别的协议时,会将链接抛给OS,转为APP处理比如itunes://开头的链接是AppleStore的私有协议,支付宝的私有协议alipay://,腾讯的tencent://等等固定协议:webview.loadUrl("javascript:alert('helloworld')");
调用nativeAPI接口方式和我们请求服务端的ajax方式类似,都是前端主动去发送一个请求,被接收处理后返回回调
混合开发中交互种类繁多,如何做到通用以58同城车商通app为例:页面跳转类型
native组件处理类型
前面提到过,Android和iOS对于前端的交互是有区别的,虽然都是采用URL拦截的方式,但是具体的方式是不一样的;iOS采用WKwebview中的messageHandlers方法,而Android采用类似ajax一样的请求;但是对于业务放来说,在和native通信时是不区分端的,这就需要封装一个交互协议的API来提供给业务方,在协议API中来区分处理Android和iOS的交互;
处理源码如下:
//区分处理Android和iOS_nativeBridge:function(param){"android"==this.osthis._andr4Native(param):"ios"==this.osthis._ios4Native(param):"ipad"==this.os&&this._ios4Native(param)},Android客户端处理
_createIframe:function(){variFrame;returniFrame=document.createElement("iframe"),iFrame.setAttribute("style","display:none;"),iFrame.setAttribute("height","0px"),iFrame.setAttribute("width","0px"),iFrame.setAttribute("frameborder","0"),iFrame}//开始是使用iframe和Android客户端通信后来改成了prompt_andr4Native:function(param){varhost=param.host;varpath=param.path;varquery=param.query;query=JSON.stringify(query)//3.5.0以上版本Android端都走新的拦截方式varurl="wubacst://"+host+"/"+path+"query="+encodeURIComponent(query);if(this._versionCompare(this._getVersion(),'3.5.0')){window.prompt(url)}else{if(!this.domReady)returnvoidthis.actionPreQueue.push(param);this.andrFrame=this._createIframe(),this.andrFrame.src="wubacst://"+host+"/"+path+"query="+encodeURIComponent(query),document.body.appendChild(this.andrFrame),this.andrFrame=null}}iOS客户端处理
//messageHandlers上绑定的WBcheshangtong对象是和iOS约定好的_ios4Native:function(param){varhost=param.host;varpath=param.path;varquery=param.query;query=JSON.stringify(query);varurl="wubacst://"+host+"/"+path+"query="+encodeURIComponent(query);if(window.webkit){try{window.webkit.messageHandlers.WBcheshangtong.postMessage(url);}}}处理好底层交互之后,在根据业务的不同,前端封装一些通用的协议,如:
整个通信协议API如下:
由于Android使用的是iframe发送请求和Android客户端进行交互的,在前端使用canvas时,iframe重复执行,导致前端重复提交协议,目前换成了prompt交互;在开发过程中有遇到这种问题的小伙伴,欢迎留言。