基于React Native的跨三端应用架构实践

一次编写,到处运行”(Write once, run anywhere )是很多前端团队孜孜以求的目标。实现这个目标,不但能以最快的速度,将应用推广到各个渠道,而且还能节省大量人力物力。

React Native的推出,为跨平台的开发带来了新的曙光。 虽然Facebook官方blog的说法React Native支持“Learn once, write anywhere.”。但经过开源社区的不断努力,React Native已经可以达到“一次编写,到处运行”的目标。可以说超过了Facebook的预期。作者在最近的几个项目中,运用React Native技术,成功实现跨越iOS,Android,Web三端的前端架构。这里将使用到的技术和过程中遇到的困难和问题揭示出来,供读者探讨。

技术选型

我们的目标是希望一套代码同时支持iOS,Android App和微信公众号内的网页(同时保留将来支持桌面浏览器的能力)。在开始重构之前,我们盘点了目前可用的一些技术:

\"\"

① SPA:single page web application,就是只有一张html页面的应用。仅在该Web页面初始化时加载相应的HTML、JavaScript、CSS。一旦页面加载完成,SPA不会因为用户的操作而进行页面的重新加载或跳转,而是利用JavaScript动态的变换HTML(采用的是div切换显示和隐藏),从而实现UI与用户的交互。

② MPA: multipage web application, 相对于SPA,MPA有多个html页面。页面间跳转刷新所有资源,公共资源(js、css等)需选择性重新加载。

本人于2012年开始接触Cordova \u0026amp; Ionic,应该说Cordova 在React-Native出现之前确实是跨平台的主流技术。但是现在是2018年,Cordova 在性能上肯定达不到我们的要求,首先被pass掉。
 
Vue.js也是我们团队的备选前端框架,主要用于桌面浏览器展示的项目。缺乏原生移动解决方案,以及实际用下来感觉template表现力比不上JSX。另外我们用到了蚂蚁金服优秀的前端控件库ant design mobile, 暂时不支持Vue。
 
2018年7月份我们对Flutter(0.5.1) 和React-Native(0.51.0)进行了一次性能比较测试。我们在Android上用Flutter和React-Native分别实现了一个含图文的新闻客户端,比较了页面加载,图片加载,页面跳转等关键性能。实测下来Flutter在List加载,跳转到详情页时都有明显掉帧。另外代码无法移植到web上。这些原因导致我们放弃了Flutter。

最终我们选择了React-Native作为我们项目的实现技术,除了上述的一些优点之外,我们在如下一些方面收益颇多。

项目架构

我们在项目中用到的前端整体架构如下图:

\"\"

以下对上图中一些技术点进行介绍:

应用支持层

作为应用和后台服务\u0026amp;原生App之间的桥梁,应用支持层需要处理诸如端到端通讯,数据加密解密,数据缓存,数据拦截,原生应用功能访问等基础服务。最大限度的屏蔽掉平台间差异,让位于其上的层尽量做到平台无关。

原生模块封装

React-Native 可以方便的封装原生应用模块。对于有UI的原生模块,既支持在一个新的ViewController(Activity)中展示, 也支持将其封装成一个View,嵌入到React-Native的上下文中。 这也是React-Native最接地气的特性,远超Cordova。在一些场景下需要等待原生模块中的事件,诸如用户操作等异步事件之后才能返回,这时需要用到Promise作为原生模块的参数。
 
比如通过调用手机摄像头,对银行卡进行扫描,这时会调用原生第三发控件的ScanCardViewController进行扫描,扫描结果通过代理函数回调。整个调用和回调的流程无法直接在一个函数中完成,这时可以用React native的Promise 实现对JS端Promise的无缝对接。

@protocol RCTBankCardScannerDelegate \u0026lt;NSObject\u0026gt;-(void)onScanCardResult:(NSDictionary *) result;@end @interface RCTBankCardScanner()\u0026lt;RCTBankCardScannerDelegate\u0026gt;@property(nonatomic, strong) RCTPromiseResolveBlock resolveBlock;@property(nonatomic, strong) RCTPromiseRejectBlock rejectBlock;@end @implementation RCTBankCardScannerRCT_EXPORT_MODULE();RCT_REMAP_METHOD(scan, resolver:(RCTPromiseResolveBlock)resolve                 rejecter:(RCTPromiseRejectBlock)reject){  //异步调用,函数本体不返回,需要保留resolve,和reject函数指针  self.resolveBlock = resolve;  self.rejectBlock = reject;  //跳转到扫描银行卡控件的ViewController  ScanCardViewController * viewController = [ScanCardViewController new];  UIViewController *rootViewController = RCTPresentedViewController();  [rootViewController presentViewController:viewController animated:YES completion:nil];} #pragma mark RCTBankCardScannerDelegate-(void)onScanCardResult:(NSDictionary *) result{  // 在原生ViewController回调处,再返回Promise的处理结果  if(result != nil \u0026amp;\u0026amp; [[result objectForKey:@\u0026quot;code\u0026quot;] isEqualToString:@\u0026quot;0\u0026quot;]){    if(self.resolveBlock != nil){      self.resolveBlock(result);    }  }else if(result != nil){    if(self.rejectBlock != nil){      self.reject
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值