跨端方案背景
一
1
起因
由于客户端Webview内嵌H5的各种受限,例如性能差、JS执行效率低以及伴随着大量的机型兼容问题,于是有了各种混合跨端开发解决方案:Hybrid、React-Native、Weex、Flutter、小程序、快应用等。
2
优势
我们知道各大应用市场对于app的发版都有规定的周期,常常各种端内需求需要集中在某一固定时间进行发版,而跨端方案可以随时发版,不受应用市场的审核限制,然而这有一个前提,开发者所运用的解决方案所对应的Native(端内原生开发)的功能都已完备,且几乎具有与Native一样的能力,例如拍照、上传等。
3
劣势
目前市面上大量的跨端解决方案很难达到传统Web开发语言的能力,例如组件方面仅提供了部分内置组件,暂不能支持所有html规范;样式能力对于不同的客户端也会出现一定的差异。总之在降低开发成本和提升效率的同时也带来了无数细小的坑。
笔者作为刚开始应用Weex的小白以Weex为例跟大家分享一下自己理解的跨端方案。
WEEX
二
1
简介
“Weex致力于使开发者能基于通用跨平台的Web开发语言和开发经验,来构建Android、iOS和Web应用。在集成WeexSDK之后,可以使用JavaScript语言和前端开发经验来开发移动应用。”目前Vue.js和Rax这两个前端框架被广泛应用于Weex页面开发。致力于将流行的Web开发技术与原生开发技术结合,在开发阶段:一个Weex页面就像开发一个普通网页一样;在运行时:Weex又充分利用了各种操作系统的原生组件和能力。
2
组件能力
Weex提供了一套基础的内置组件,例如
在框架内容,Weex使用原生组件进行渲染,这一点极大的提升了各种平台、系统、机型的兼容性,但正是因为原生组件,在不同平台上会产生一定的视觉差异,例如组件在不同平台的渲染效果有所差异。
3
模块能力
通常通过 weex.requireModule("xxx")来引入相应的模块,引入之后便可以调用该模块提供的各种方法,Weex提供了网络请求、动画、导航、存储等内置模块。
除了内置模块,Weex同时也支持端内封装自定义模块提供前端调用,利用JSBridge将JS与Native联系起来。
4
JS与Native之间的通信原理
假设我们现在要在Weex页面实现一个拍照功能,对于前端来说,只需要调用Native提供的API即可,使开发者可以在weex页面内调用端内原生的拍照功能,而JSBridge便是Native能提供给API给JS调用的答案。简单来说,JSBridge就是JS与Native之间的桥梁,让两者能够互相调用
以android为例,其核心原理为:(以下代码源自Github:https://github.com/lzyzsd/JsBridge)
native端注册函数供Javascript调用:
// 下面webview是一个自定义的WebView,继承Android原生的WebView对象webView.registerHandler("submitFromWeb", new BridgeHandler() {@Overridepublic void handler(String data, CallBackFunction function) {Log.i(TAG, "handler = submitFromWeb, data from web = " + data);function.onCallBack("submitFromWeb exe, response data from Java");}});
上述则表明了,在Android端注册了一个名为submitFromWeb的函数供Javascript调用,handler为具体的执行内容。String类型的data是JavaScript端调用时传过来的参数,CallBackFunction类型的function是用来将执行的结果回传给JavaScript。
JavaScript调用native端提供的函数
// WebViewJavascriptBridge是提前注入的一个全局变量用于javascript调用native提供的函数WebViewJavascriptBridge.callHandler('submitFromWeb',{'param': str},// 调用native函数成功后的回调函数function callback(responseData){document.getElementById("show").innerHTML = "send get responseData from java, data = " + responseData});
上述表明JS通过提前注入的WebViewJavascriptBridge对象调用native端提供的submitFromWeb函数,传递的参数为{'param':str},调用结束后会回调callback函数。
应用
三
对于一般的app应用少不了网络请求,因此笔者从网络请求为例,简单分享一下应用案例。
在Weex中提供了stram模块来完成基本的网络请求能力,例如GET、POST请求等,用于在组件的生命周期内与服务端进行交互。
API
fetch(options, callback, progressCallback)
options为请求配置项,包括Http请求方法、url、header、body、type等,callback为响应回调,包括状态码,响应数据等。
引入
var stream = weex.requireModule("stream");
请求封装
对于一个长期维护的端内项目通常需要有一个低耦合的接口请求封装函数,通常大部分请求参数需要带上用户的token信息、地理位置信息等,因此我们可以通过端内封装的JSBridge直接获取已经在端内登录的用户信息,地理信息同理。获取这些信息之后再利用Promise.all()来处理最终的业务请求。
requestAgent(obj, isService = false) {var userLocationInfoPromise = new Promise(function (resolve, reject){bridge.getLocationInfo((data) => {resolve(data)});});var userInfoPromise = new Promise(function (resolve, reject){bridge.getUserInfo((data) => {resolve(data)});});Promise.all([userLocationInfoPromise, userInfoPromise]).then((items) => {var userLocationInfo = items[0];var userInfo = items[1];var method = obj.methodswitch (method) {case "GET":break;case "POST":break;}stream.fetch(options, ret => {if (!ret.ok) {obj.fail(ret.statusText)return}var bizRet = ret.dataif (bizRet.errno != 0) {obj.fail(bizRet.errmsg,bizRet.errno);} else {obj.success(bizRet.data);}});});},
调用示例
requestAgent({method: 'POST/GET',path: '/api/donut/uploadResource',headers: { "Content-Type": "application/x-www-form-urlencoded;charset=utf-8", },body: obj.body,type: 'json',rawBody: raw,params: {key: value} //根据 GET 和 POST 自动放在 query 或 bodysuccess: function,fail: function});
上面的代码我们可以看到,这样的接口请求封装不仅仅用到了weex的内置模块stream,同样也运用到了自定义模块bridge,通过bridge模块便可以实现JS与Native的通信,去获取当前用户的登录信息和地理信息;避免在每个请求中都插入这些信息的请求函数,同样也避免了定义冗余变量去存储这些信息,也达到了降低耦合的效果。
WEEX跨端方案总结
四
前端页面原生渲染,增强前端页面体验
一次开发支持多端(Android、iOS、H5)运行
页面更新不依赖版本发布,提升迭代发布效率
单页面开发能力强大
如果尝试利用Weex独立开发App比较困难,它的Native能力并没有ReactNative那样强大且全面,Weex更注重Web的开发体验,强调像开发Web网页一样开发跨平台APP页面,官方也较推荐Weex和Native混合开发方式开发App,即将Weex作为一个组件融入到Native App中,替换传统的Hybrid模式。
因此我们可以大胆猜测,类似上面的这样一个页面,底部导航可以利用Native进行维护,以达到更多机型的兼容,中间的Feed流部分可以选择用Weex进行维护,可以根据业务需求在feed中插入相应的模块需求(聚划算、百亿补贴…),而对于每个feed item的落地页,如果在不复杂的情况下完全可以利用H5进行维护。虽然看似同一个app运用了多种解决方案,但这样便把不同的业务模块根据规模和需求隔离开,交给不同的人员进行维护迭代,进一步提升开发迭代效率。
总的来说,weex是一套很好的跨端解决方案。虽然有很多细节不支持,但总体上提升了移动端的开发效率。