React Native自定义组件与输出方法详解
简介
如果你看的这一篇,需要你对ReactNative的开发有一定的了解,此文讲的是在ReactNative提供的组件不能满足需求,或者native用于较成熟的组件想要输出,那么就需要用到自定义组件了.
通过该文,我们也可以对native和JS交互方式进行初步了解,关于输出方法内部实现,我们下一篇再剖.
Nativemodule
nativemodule就是实现了RCTBridgeModule协议的OC类.RCT就是ReaCT的缩写.
具体步骤如下
- 引入#import
类,然后遵守RCTBridgeModule协议. - 实现RCT_EXPORT_MODULE(customName)方法.customName是自定义的组件名,如果不填默认为当前类名.这个组件名是用于向JS输出.
输出组建后,默认不会向JS输出任何方法,想要输出方法,需要自定义实现方法输出,使用宏RCT_EXPORT_METHOD()
RCT_EXPORT_METHOD(addEvent:(NSString*)namelocation:(NSString*)location)
{
RCTLogInfo(@"Pretendingtocreateanevent%@at%@",name,location);
}
对于JS端,调用时就可以如下
import{NativeModules}from'react-native';
varCustomName=NativeModules.CalendarManager;
CustomName.addEvent('BirthdayParty','4PrivetDrive,Surrey');
注意
向JS输出的方法名,是RCT_EXPORT_METHOD之后,第一个冒号之前的名字.如果native已经暴露了多个冒号之前同名的方法,RN提供了RCT_REMAP_METHOD()来制定方法名.
另外一点,RCT_EXPORT_METHOD回调进入的方法,默认并不在主线程,如果想要进行主线程的方法调用,需要手动进行dispatch_async(dispatch_get_main_queue(),^{});回到主线程
RCT_EXPORT_METHOD参数
RCT_EXPORT_METHOD支持如下的参数类型
- string(NSString)
- number(NSInteger,float,double,CGFloat,NSNumber)
- boolean(BOOL,NSNumber)
- array(NSArray)ofanytypesfromthislist
- object(NSDictionary)withstringkeysandvaluesofanytypefromthislist
- function(RCTResponseSenderBlock)
也支持所有RCTConvert支持的类型.
回调
nativemodule支持回调类型RCTResponseSenderBlock
RCT_EXPORT_METHOD(findEvents:(RCTResponseSenderBlock)callback)
{
NSArray*events=...
callback(@[[NSNullnull],events]);
}
RCTResponseSenderBlock只支持一个参数:一个包含了多个参数的数组.在JS端可以如下,默认第一个参数是error.当没有错误时error为空.
CalendarManager.findEvents((error,events)=>{
if(error){
console.error(error);
}else{
this.setState({events:events});
}
});
nativemodule只能调用一次回调.如果想传递错误,通过RCTUtils.h类中的RCTMakeError来创建.
Promise
Promise是用于实现异步操作async/await的工具类.如果最后一个参数类型为RCTPromiseResolveBlock和RCTPromiseRejectBlock,JS端会返回一个promise对象,进行一步操作.
RCT_REMAP_METHOD(findEvents,
findEventsWithResolver:(RCTPromiseResolveBlock)resolve
rejecter:(RCTPromiseRejectBlock)reject)
{
NSArray*events=...
if(events){
resolve(events);
}else{
NSError*error=...
reject(@"no_events",@"Therewerenoevents",error);
}
}
JS端因为获取的是promise对象,可以使用await关键字进行异步调用并等待结果
asyncfunctionupdateEvents(){
try{
varevents=awaitCalendarManager.findEvents();
this.setState({events});
}catch(e){
console.error(e);
}
}
updateEvents();
关于线程
JS执行nativemodule是在一个单独的线程实现的,可以通过-(dispatch_queue_t)methodQueue来控制.如果返回主线程,所有执行的方法会在主线程被执行.
-(dispatch_queue_t)methodQueue
{
returndispatch_get_main_queue();
}
方法methodQueue之后在组件初始化时被调用一次.
输出实例
除了可以输出方法,还有输出实例.
-(NSDictionary*)constantsToExport
{
return@{@"firstDayOfTheWeek":@"Monday"};
}
在JS端可以直接获取console.log(CalendarManager.firstDayOfTheWeek);
只有在初始化时实例输出才是有效的,如果在运行时修改constantsToExport是不会影响JS环境的数据的.
输出枚举
通过typedefNS_ENUM()定义的枚举,可以通过增加RCTConvert的扩展来完成
@implementationRCTConvert(StatusBarAnimation)
RCT_ENUM_CONVERTER(UIStatusBarAnimation,(@{@"statusBarAnimationNone":@(UIStatusBarAnimationNone),
@"statusBarAnimationFade":@(UIStatusBarAnimationFade),
@"statusBarAnimationSlide":@(UIStatusBarAnimationSlide)}),
UIStatusBarAnimationNone,integerValue)
@end
之后就可以通过输出属性和方法等方式在JS中使用了.
native向JS发方法
想给JS发方法,可以继承类RCTEventEmitter,实现supportedEvents方法,然后通过调用selfsendEventWithName:即可.
RCT_EXPORT_MODULE(); -(NSArray*)supportedEvents { return@[@"EventReminder"]; } -(void)calendarEventReminderReceived:(NSNotification*)notification { NSString*eventName=notification.userInfo[@"name"]; [selfsendEventWithName:@"EventReminder"body:@{@"name":eventName}]; }
JS端可以通过NativeEventEmitter进行注册和调用
import{NativeEventEmitter,NativeModules}from'react-native';
const{CalendarManager}=NativeModules;
constcalendarManagerEmitter=newNativeEventEmitter(CalendarManager);
constsubscription=calendarManagerEmitter.addListener(
'EventReminder',
(reminder)=>console.log(reminder.name)
);
...
//Don'tforgettounsubscribe,typicallyincomponentWillUnmount
subscription.remove();
注意取消订阅,一般在componentWillUnmount内执行.
客户端可以通过一些方式获取JS注册和移除订阅的事件,来优化只在有订阅者的情况下才发送事件.
//Willbecalledwhenthismodule'sfirstlistenerisadded.
-(void)startObserving{
hasListeners=YES;
//Setupanyupstreamlistenersorbackgroundtasksasnecessary
}
//Willbecalledwhenthismodule'slastlistenerisremoved,orondealloc.
-(void)stopObserving{
hasListeners=NO;
//Removeupstreamlisteners,stopunnecessarybackgroundtasks
}
资料
nativemodules官文
总结
以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对毛票票的支持。
声明:本文内容来源于网络,版权归原作者所有,内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任。如果您发现有涉嫌版权的内容,欢迎发送邮件至:czq8825#qq.com(发邮件时,请将#更换为@)进行举报,并提供相关证据,一经查实,本站将立刻删除涉嫌侵权内容。