有时候 App 需要访问平台 API,但 React Native 可能还没有相应的模块封装;或者你需要复用 Objective-C、Swift 或 C++代码,而不是用 JavaScript 重新实现一遍;又或者你需要实现某些高性能、多线程的代码,譬如图片处理、数据库、或者各种高级扩展等等。
React Native 设计为可以在其基础上编写真正的原生代码,并且可以访问平台所有的能力
在 React Native 中,一个“原生模块”就是一个实现了“RCTBridgeModule”协议的 Objective-C 类,其中 RCT 是 ReaCT 的缩写。
// CalendarManager.h
#import <React/RCTBridgeModule.h>
@interface CalendarManager : NSObject <RCTBridgeModule>
@end
为了实现RCTBridgeModule协议,你的类需要包含RCT_EXPORT_MODULE()宏。这个宏也可以添加一个参数用来指定在 JavaScript 中访问这个模块的名字。如果你不指定,默认就会使用这个 Objective-C 类的名字。如果类名以 RCT 开头,则 JavaScript 端引入的模块名会自动移除这个前缀。
// CalendarManager.m
#import "CalendarManager.h"
@implementation CalendarManager
// To export a module named CalendarManager
RCT_EXPORT_MODULE();
// This would name the module AwesomeCalendarManager instead
// RCT_EXPORT_MODULE(AwesomeCalendarManager);
@end
你必须明确的声明要给 JavaScript 导出的方法,否则 React Native 不会导出任何方法。声明通过RCT_EXPORT_METHOD()宏来实现:
#import "CalendarManager.h"
#import <React/RCTLog.h>
@implementation CalendarManager
RCT_EXPORT_MODULE();
RCT_EXPORT_METHOD(addEvent:(NSString *)name location:(NSString *)location)
{
RCTLogInfo(@"Pretending to create an event %@ at %@", name, location);
}
@end
现在从 Javascript 里可以这样调用这个方法:
import {NativeModules} from 'react-native';
const CalendarManager = NativeModules.CalendarManager;
CalendarManager.addEvent('Birthday Party', '4 Privet Drive, Surrey');
RCT_EXPORT_METHOD 支持所有标准 JSON 类型,包括:
NSString)NSInteger, float, double, CGFloat, NSNumber)BOOL, NSNumber)NSArray) 可包含本列表中任意类型NSDictionary) 可包含 string 类型的键和本列表中任意类型的值RCTResponseSenderBlock)原生模块还支持一种特殊的参数——回调函数。它提供了一个函数来把返回值传回给 JavaScript。
RCT_EXPORT_METHOD(findEvents:(RCTResponseSenderBlock)callback)
{
NSArray *events = ...
callback(@[[NSNull null], events]);
}
RCTResponseSenderBlock只接受一个参数——传递给 JavaScript 回调函数的参数数组。在上面这个例子里我们用 Node.js 的常用习惯:第一个参数是一个错误对象(没有发生错误的时候为 null),而剩下的部分是函数的返回值。
CalendarManager.findEvents((error, events) => {
if (error) {
console.error(error);
} else {
this.setState({events: events});
}
});