深入理解反应本地原生模块与JS模块通信的几种方式

  

每种语言都有自己的设计理念,语法,运行环境,这也导致了不同语言间相互交流通信时必须要有中介来翻译,如JAVA与C/c++通过JNI来交流,OC与C/c++需要在功能文件混编,而JAVA/OC与Lua通信时需要通过C/c++语言来做中介。那么在React-Native中JSX是如何与底层模块进行通信的呢?这里主要以iOS系统来做说明。

  

<强>原理

  

通信本质上是信息的交流,具体到计算机语言则是数据的流动。应用中数据在React-Native与原生模块间的流动与共享,完成了与用户的交互,达成了应用的目标.React-Native与OC间通信的数据只能是下面的几种类型(前为JS类型,后为OC类型):

  
      <李> string-NSString李   <李>数量- int/NSInteger/浮动/双/NSNumber李   <李>布尔- BOOL/NSNumber李   <李>数组——NSArray李   <李>对象——NSDictionary (NSString型键,值可以为这里的其它类型)   <李> func - RCTResponseSenderBlock李   
  

其它类型的数据需要通过一定的规则转换成这几种类型后(一般都会转换成JSON串)再通信。

  

React-Native本质是通过JavaScriptCore.framework实现JS代码与OC代码间的互动。因此下面说的几种方式在本质原理上都是相同的,不同的地方只是在于实现形式与方法的差别。

  

<强>函数调用

  

在将原生模块封装并提供给React-Native使用时,可以通过RCT_EXPORT_METHOD()宏向React-Native侧定义其可以调用的接口函数,完成两模块间的通信。

     //定义了startVPN接口,React-Native将VPN的具体参数通过该接口传入到原生模块,开启指定的VPN   RCT_EXPORT_METHOD (startVPN:(NSDictionary *)配置)   {   LSShadowSocksDataMode *模式=[[LSShadowSocksDataMode alloc] initWithDictionary:配置);   (自我。经理startVPN:模式);   }   之前      

除了传入数据外,通过可以通过这种方式从原生侧获取数据。最容易想到的是通过返回值获取,可惜的是RCT_EXPORT_METHOD宏不支持返回值,不过其提供了另外一种实现返回值的方式:

        RCT_EXPORT_METHOD (isOpen: (RCTResponseSenderBlock)回调)   {   BOOL开放=[自我。管理器状态);   回调(@ [[NSNull null], @[@(打开)]]);   }   之前      

通过回调函数的形式实现返回值的效果,达到了数据交换的目的。

  

<强>属性共享

  

这种方式主要针对于UI控件来说的.React-Native中最基础的UI类型是RCTRootView,该类有一个初始化方法initWithBridge: moduleName: initialProperties:第三个参数initialProperties表示的是UI控件的初始属性值,类型为NSDictionary,其最终会被同步到由第二个参数定义的React-Native类的道具中,即完成了两个模块间的数据交流。

        NSArray * imageList=@ [@“https://cache.yisu.com/upload/information/20200622/114/70935.png”,   @“https://cache.yisu.com/upload/information/20200622/114/70936.png”);      NSDictionary *道具=@{@“图像”:imageList};      RCTRootView * rootView=[[RCTRootView alloc] initWithBridge:桥   moduleName: @“ImageBrowserApp”   initialProperties道具):;   之前            进口的反应,从“反应”{组件};   进口{   AppRegistry,   看来,   形象,   从“react-native”};      类ImageBrowserApp扩展组件{   renderImage (imgURI) {   回报(   & lt;图像源={{uri: imgURI}}/比;   );   }   呈现(){   回报(   & lt; View>   {this.props.images.map (this.renderImage)}   & lt;/View>   );   }   }      AppRegistry。registerComponent (ImageBrowserApp,()=比;ImageBrowserApp);      之前      

初始化接口只能在UI组件建立时使用,如果需要在UI组件的生命周期内通信呢,RCTRootView提供了appProperties这样一种机制:

        NSArray * imageList=@ [@“https://cache.yisu.com/upload/information/20200622/114/70937.png”,   @“https://cache.yisu.com/upload/information/20200622/114/70939.png”);   rootView。appProperties=@{@“图像”:imageList};      

<强>通知

  

OC中使用NSNotificationCenter向整个应用发送通知,所有对该通知感兴趣的对象都会获得该通知并执行相应的动作。

  

React-Native中也提供有类似的机制:RCTEventEmitter。原生模块继承该类后,就可以向React-Native侧发送通知,而React-Native就能够接收到该通知,并处理一并传送过来的数据了。

深入理解反应本地原生模块与JS模块通信的几种方式