当前位置: 移动技术网 > 移动技术>移动开发>IOS > React Native自定义组件与输出方法详解

React Native自定义组件与输出方法详解

2019年07月24日  | 移动技术网移动技术  | 我要评论

简介

如果你看的这一篇,需要你对reactnative的开发有一定的了解,此文讲的是在reactnative提供的组件不能满足需求,或者native用于较成熟的组件想要输出,那么就需要用到自定义组件了.

通过该文,我们也可以对native和js交互方式进行初步了解,关于输出方法内部实现,我们下一篇再剖.

native module

native module就是实现了rctbridgemodule协议的oc类.rct就是react的缩写.

具体步骤如下

  • 引入#import <react/rctbridgemodule.h>类,然后遵守rctbridgemodule协议.
  • 实现rct_export_module(customname)方法. customname是自定义的组件名,如果不填默认为当前类名.这个组件名是用于向js输出.

输出组建后,默认不会向js输出任何方法,想要输出方法,需要自定义实现方法输出,使用宏rct_export_method ()

rct_export_method(addevent:(nsstring *)name location:(nsstring *)location)
{
 rctloginfo(@"pretending to create an event %@ at %@", name, location);
}

对于js端,调用时就可以如下

import {nativemodules} from 'react-native';
var customname = nativemodules.calendarmanager;
customname.addevent('birthday party', '4 privet drive, 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) of any types from this list
  • object (nsdictionary) with string keys and values of any type from this list
  • function (rctresponsesenderblock)

也支持所有rctconvert支持的类型.

回调

native module支持回调类型rctresponsesenderblock

rct_export_method(findevents:(rctresponsesenderblock)callback)
{
 nsarray *events = ...
 callback(@[[nsnull null], events]);
}

rctresponsesenderblock只支持一个参数:一个包含了多个参数的数组.在js端可以如下,默认第一个参数是error.当没有错误时error为空.

calendarmanager.findevents((error, events) => {
 if (error) {
 console.error(error);
 } else {
 this.setstate({events: events});
 }
});

native module只能调用一次回调.如果想传递错误,通过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", @"there were no events", error);
 }
}

js端因为获取的是promise对象,可以使用await关键字进行异步调用并等待结果

async function updateevents() {
 try {
 var events = await calendarmanager.findevents();

 this.setstate({events});
 } catch (e) {
 console.error(e);
 }
}

updateevents();

关于线程

js执行native module是在一个单独的线程实现的,可以通过- (dispatch_queue_t)methodqueue来控制.如果返回主线程,所有执行的方法会在主线程被执行.

- (dispatch_queue_t)methodqueue
{
 return dispatch_get_main_queue();
}

方法methodqueue之后在组件初始化时被调用一次.

输出实例

除了可以输出方法,还有输出实例.

- (nsdictionary *)constantstoexport
{
 return @{ @"firstdayoftheweek": @"monday" };
}

在js端可以直接获取console.log(calendarmanager.firstdayoftheweek);

只有在初始化时实例输出才是有效的,如果在运行时修改constantstoexport是不会影响js环境的数据的.

输出枚举

通过typedef ns_enum()定义的枚举,可以通过增加rctconvert的扩展来完成

@implementation rctconvert (statusbaranimation)
 rct_enum_converter(uistatusbaranimation, (@{ @"statusbaranimationnone" : @(uistatusbaranimationnone),
            @"statusbaranimationfade" : @(uistatusbaranimationfade),
            @"statusbaranimationslide" : @(uistatusbaranimationslide)}),
      uistatusbaranimationnone, integervalue)
@end

之后就可以通过输出属性和方法等方式在js中使用了.

native向js发方法

想给js发方法,可以继承类rcteventemitter,实现supportedevents方法,然后通过调用self sendeventwithname:即可.

rct_export_module();

- (nsarray<nsstring *> *)supportedevents
{
 return @[@"eventreminder"];
}

- (void)calendareventreminderreceived:(nsnotification *)notification
{
 nsstring *eventname = notification.userinfo[@"name"];
 [self sendeventwithname:@"eventreminder" body:@{@"name": eventname}];
}

js端可以通过nativeeventemitter进行注册和调用

import { nativeeventemitter, nativemodules } from 'react-native';
const { calendarmanager } = nativemodules;

const calendarmanageremitter = new nativeeventemitter(calendarmanager);

const subscription = calendarmanageremitter.addlistener(
 'eventreminder',
 (reminder) => console.log(reminder.name)
);
...
// don't forget to unsubscribe, typically in componentwillunmount
subscription.remove();

注意取消订阅,一般在componentwillunmount内执行.

客户端可以通过一些方式获取js注册和移除订阅的事件,来优化只在有订阅者的情况下才发送事件.

// will be called when this module's first listener is added.
-(void)startobserving {
 haslisteners = yes;
 // set up any upstream listeners or background tasks as necessary
}

// will be called when this module's last listener is removed, or on dealloc.
-(void)stopobserving {
 haslisteners = no;
 // remove upstream listeners, stop unnecessary background tasks
}

资料

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对移动技术网的支持。

如对本文有疑问, 点击进行留言回复!!

相关文章:

验证码:
移动技术网