React Native与Native之间通信
一、简介本文将通过Simple Demo的首页作为例子讲解React Native与Native之间通信。希望帮助刚接触RN的同学了解和选择合适的方式去传输数据。Simple Demo首页代码如下: Simple Demo首页AdrHomePageReactView继承于AdrReactView; #import "AdrHomePageReactView.h" @interface AdrHomePageReactView : AdrReactView @end AdrHomePageReactView.m #import "AdrHomePageReactView.h" @implementation AdrHomePageReactView -(NSString *)componentModelName { return @"Homepage"; } @end AdrReactView.m #import "AdrReactView.h" #import <RCTRootView.h> #import "AdrGlobalVar.h" @implementation AdrReactView - (instancetype)initWithProperties:(NSDictionary *)propertiesDic { self = [super init]; if (self) { [self configureRCTRootView:propertiesDic]; } return self; } - (void)configureRCTRootView:(NSDictionary *)propertiesDic { RCTRootView *rootView = [[RCTRootView alloc] initWithBridge:[AdrGlobalVar sharedAdrGlobalVar].bridge moduleName:[self componentModelName] initialProperties:propertiesDic]; rootView.frame = self.bounds; [self addSubview:rootView]; } - (NSString *)componentModelName { return @""; } @end 二、数据通信的方式1.Native通过创建RCTRootView传入属性通过Native代码创建RN的View时传入Properties,由Native传入Properties(字典),RN通过constructor(props)读取到对应keyValue。 //RN任意门测试主页面 AdrHomePageReactView *homepageView = [[AdrHomePageReactView alloc] initWithProperties:@{@"userName":@"Kilolo"}]; homepageView.frame = self.view.bounds; [self.view addSubview:homepageView]; RN在构造函数接收到props constructor(props){ super(props); this.state = { NonUserSystemDisable:true,FYZTDisable:false,YZTDisable:false,LogoutDisable:true,}; console.log('initProps:'+this.props.userName); } 输出结果:
2.Native导出常量ViewController导出Module及Constants RCT_EXPORT_MODULE(); -(NSDictionary<NSString *,id> *)constantsToExport { return @{@"userPassword":@"mima123"}; } RN代码: import { NativeModules,} from 'react-native'; var ViewController = NativeModules.ViewController; componentDidMount(){ console.log('componentDidMount'); console.log('userPassword:'+ViewController.userPassword); } 输出结果:
3.Native导出方法Native,在ViewController中导出Module及通过RCT_EXPORT_METHOD导出方法给RN, RCT_EXPORT_MODULE(); //测试页面 RCT_EXPORT_METHOD(rnShowFunctionTestView) { [self showFunctionTestView]; }; RN可以传数据给Native,调用Native的方法,RN调用代码: ViewController.rnShowFunctionTestView() 4.RN注册通知,Native发送通知Native增加属性bridge,注意属性名bridge不可以随意更改。因为RN会对bridge自动赋值;若更改了,则需要自己找到当前RN页面所使用的bridge。 @property(strong,nonatomic) RCTBridge *bridge; [self.bridge.eventDispatcher sendAppEventWithName:kAdrssoticketChangeNotification body:@{@"isResponse":logoutBtn.enabled?@"true":@"false"}]; RN在componentDidMount的生命周期中注册通知,在componentWillUnMount中移除通知。 componentDidMount(){ var registerLogoutBottonResponseNotification = NativeAppEventEmitter.addListener( 'AdrssoticketChangeNotification',(reminder) => { if (reminder.isResponse === 'true'){ this.setState({LogoutDisable:false}); }else if (reminder.isResponse === 'false'){ this.setState({LogoutDisable:true}); } console.log('reminder.isResponse:'+reminder.isResponse); } ); } componentWillUnmount() { registerLogoutBottonResponseNotification.remove(); } 5.回调方式RN调用Native方法,Native通过block把数据传给RN。 (1)RCTResponseSenderBlock Native中代码: RCT_REMAP_METHOD(_scanQRCode:(RCTResponseSenderBlock)callback) { dispatch_async(dispatch_get_main_queue(),^{ callback(); }); } RCTResponseSenderBlock只接受一个参数,传递给RN回调函数的参数数组. RN中的代码: AdrInterface._scanQRCode((events) => { console.log(evets); }) (2)RCTPromiseResolveBlock和RCTPromiseRejectBlock Native代码: RCT_REMAP_METHOD(_scanQRCode,resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) { dispatch_async(dispatch_get_main_queue(),^{ [self scanQRCode:nil callBack:^(NSDictionary *info,AdrECallBackStatus status) { if (status == AdrECallBackStatus_Succ) { resolve(info); }else if (status == AdrECallBackStatus_Fail){ NSError *error = [[NSError alloc] init]; reject(@"code",info[@"error"],error); } }]; }); } RN代码: AdrInterface._scanQRCode() .then(value => {console.log('qrcode:',value['value'])}) .catch(error => {console.log('error:')}) .then()括号中的方法是成功回调;.catch()是失败回调,能捕捉到_scanQRCode( )和.then( )抛出异常。建议不要把成功和失败的方法都传入then作为参数,这样不能捕捉到.then的失败异常。 另:Promise对象能使用Promise.all()和Promise.race()等处理复杂的异步操作,详情请参考http://es6.ruanyifeng.com/#do... 三、结语鉴于接触RN和ES6不久,如果本文中有错误的,请大家指出。同时也欢迎大家讨论更好的方式,谢谢。 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |