每种语言都有自己的设计理念、语法、运行环境,这也导致了不同语言间相互交流通信时必须要有中介来翻译,如JAVA与C/C++通过JNI来交流、OC与C/C++需要在.mm文件混编、而JAVA/OC与Lua通信时需要通过C/C++语言来做中介。那么在React-Native中JSX是如何与底层模块进行通信的呢?这里主要以iOS系统来做说明。
原理
通信本质上是信息的交流,具体到计算机语言则是数据的流动。应用中数据在React-Native与原生模块间的流动与共享,完成了与用户的交互,达成了应用的目标。React-Native与OC间通信的数据只能是下面的几种类型(前为JS类型,后为OC类型):
- string-NSString
- number - int/NSInteger/float/double/NSNumber
- boolean - BOOL/NSNumber
- array - NSArray
- object - NSDictionary(NSString型key, value可以为这里的其它类型)
- 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*)config) { LSShadowSocksDataMode* mode = [[LSShadowSocksDataMode alloc] initWithDictionary:config]; [self.manager startVPN:mode]; }
除了传入数据外,通过可以通过这种方式从原生侧获取数据。最容易想到的是通过返回值获取,可惜的是RCT_EXPORT_METHOD宏不支持返回值,不过其提供了另外一种实现返回值的方式:
RCT_EXPORT_METHOD(isOpen:(RCTResponseSenderBlock)callback) { BOOL open = [self.manager status]; callback(@[[NSNull null], @[@(open)]]); }
通过回调函数的形式实现返回值的效果,达到了数据交换的目的。
属性共享
这种方式主要针对于UI控件来说的。React-Native中最基础的UI类型是RCTRootView,该类有一个初始化方法initWithBridge:moduleName:initialProperties:,第三个参数initialProperties表示的是UI控件的初始属性值,类型为NSDictionary,其最终会被同步到由第二个参数定义的React-Native类的props中,即完成了两个模块间的数据交流。
NSArray *imageList = @[@"http://foo.com/bar1.png", @"http://foo.com/bar2.png"]; NSDictionary *props = @{@"images" : imageList}; RCTRootView *rootView = [[RCTRootView alloc] initWithBridge:bridge moduleName:@"ImageBrowserApp" initialProperties:props];
import React, { Component } from 'react'; import { AppRegistry, View, Image, } from 'react-native'; class ImageBrowserApp extends Component { renderImage(imgURI) { return ( <Image source={{uri: imgURI}} /> ); } render() { return ( <View> {this.props.images.map(this.renderImage)} </View> ); } } AppRegistry.registerComponent('ImageBrowserApp', () => ImageBrowserApp);
初始化接口只能在UI组件建立时使用,如果需要在UI组件的生命周期内通信呢,RCTRootView提供了appProperties这样一种机制:
NSArray *imageList = @[@"http://foo.com/bar3.png", @"http://foo.com/bar4.png"]; rootView.appProperties = @{@"images" : imageList};
通知
OC中使用NSNotificationCenter向整个应用发送通知,所有对该通知感兴趣的对象都会获得该通知并执行相应的动作。
React-Native中也提供有类似的机制:RCTEventEmitter。原生模块继承该类后,就可以向React-Native侧发送通知,而React-Native就能够接收到该通知,并处理一并传送过来的数据了。
-(void)vpnStatusChanged:(NSNotification*)notification { NEVPNStatus status = [self.manager status]; NSString* value = nil; switch (status) { case NEVPNStatusReasserting: value = @"重新连接中"; break; case NEVPNStatusConnecting: value = @"连接中"; break; case NEVPNStatusConnected: value = @"已连接"; break; case NEVPNStatusDisconnecting: value = @"断开连接中"; break; case NEVPNStatusDisconnected: case NEVPNStatusInvalid: value = @"末连接"; break; default: break; } if(value){ [self sendEventWithName:@"VpnStatus" body:@{@"status":value}]; } }
这里将VPN的状态通过通知发送到React-Native侧,由React-Native将VPN的状态显示的UI界面上。
小结
这里只是简单的介绍了两种语言间几种常用的通信方式,并没有涉及到其背后的实现细节。对这方面感兴趣的同学,不妨参阅下面的两篇文章:
React Native通信机制详解
浅析ReactNative之通信机制
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。
免责声明:本站资源来自互联网收集,仅供用于学习和交流,请遵循相关法律法规,本站一切资源不代表本站立场,如有侵权、后门、不妥请联系本站删除!
稳了!魔兽国服回归的3条重磅消息!官宣时间再确认!
昨天有一位朋友在大神群里分享,自己亚服账号被封号之后居然弹出了国服的封号信息对话框。
这里面让他访问的是一个国服的战网网址,com.cn和后面的zh都非常明白地表明这就是国服战网。
而他在复制这个网址并且进行登录之后,确实是网易的网址,也就是我们熟悉的停服之后国服发布的暴雪游戏产品运营到期开放退款的说明。这是一件比较奇怪的事情,因为以前都没有出现这样的情况,现在突然提示跳转到国服战网的网址,是不是说明了简体中文客户端已经开始进行更新了呢?
更新日志
- 群星.2022-福茂巨星·时空之轮日本唱片志系列DISC2范晓萱-RAIN【福茂】【WAV+CUE】
- 王闻-《男人四十4》[正版CD低速原抓WAV+CUE]
- 青燕子-八只眼演唱组《爱心》[WAV+CUE]
- 祁露想着你的好》WAV+CUE
- 陈致逸《赴梦之约 游戏主题原声音乐》[FLAC/分轨][159.96MB]
- 贵族音乐《睡眠自然流水声 ASMR白噪音背景音》[320K/MP3][155.72MB]
- 贵族音乐《睡眠自然流水声 ASMR白噪音背景音》[FLAC/分轨][857.58MB]
- 朱昕嵘《琴意绵绵6N纯银SQCD》[WAV+CUE]
- 降央卓玛《草原情6N纯银SQCD》WAV+CUE
- 傲日格乐《黑马琴HQCD》[WAV+CUE]
- 群星.2022-福茂巨星·时空之轮日本唱片志系列DISC3范晓萱-自言自语【福茂】【WAV+CUE】
- 群星.2022-福茂巨星·时空之轮日本唱片志系列DISC4那英-白天不懂夜的黑【福茂】【WAV+CUE】
- 群星.2015-华丽上班族电影原声大碟【大右音乐】【WAV+CUE】
- 陈粒《乌有乡地图》[320K/MP3][21.81MB]
- 陈粒《乌有乡地图》[FLAC/分轨][398.39MB]