React Native本身已经提供很多可用的模块和组件,有一部分我们需要的模块和组件仍然无法直接提供,需要借助原生的代码来提供。封装原生模块和视图导出使用,也可以让React Native拥有android和ios平台的强大生态链和使用众多第三方类库。
原生模块
以下以支付宝支付模块为实例
android支付宝
模块实现
AlipayModule.java
// 模块继承自ReactContextBaseJavaModule
public class AlipayModule extends ReactContextBaseJavaModule {
// 默认构造方法
public AlipayModule(ReactApplicationContext reactContext) {
super(reactContext);
}
// 模块名
@Override
public String getName() {
return "AlipayModule";
}
// 添加@ReactMethod注解导出方法
// promise需放在最后
@ReactMethod
public void pay(final String orderInfo, final Promise promise) {
Runnable runnable = new Runnable() {
@Override
public void run() {
PayTask alipay = new PayTask(getCurrentActivity());
Map<String, String> result = alipay.payV2(orderInfo,true);
Log.i("AlipayModule", "resultStatus: " + result.get("resultStatus"));
if ("9000".equals(result.get("resultStatus"))) {
promise.resolve(true);
} else {
promise.resolve(false);
}
}
};
Thread thread = new Thread(runnable);
thread.start();
}
}
复制代码
模块注册
MyReactPackage.java
// 实现ReactPackage接口
// 用于注册导出的模块和视图
public class MyReactPackage implements ReactPackage {
// 原生模块注册
@Override
public List<NativeModule> createNativeModules(ReactApplicationContext reactContext) {
return Arrays.<NativeModule>asList(
new AlipayModule(reactContext)
);
}
// 原生视图注册
@Override
public List<ViewManager> createViewManagers(ReactApplicationContext reactContext) {
return Arrays.<ViewManager>asList();
}
}
复制代码
包注册
在MainApplication getPackages方法中添加new MyReactPackage()
ios支付宝
模块实现
AlipayModule.h
#import <React/RCTBridgeModule.h>
@interface AlipayModule : NSObject<RCTBridgeModule>
@end
复制代码
AlipayModule.m
#import "AlipayModule.h"
#import <AlipaySDK/AlipaySDK.h>
@interface AlipayModule()
@end
@implementation AlipayModule
// 添加宏,导出模块
RCT_EXPORT_MODULE();
// 使用宏,导出方法,resolve和reject为promise方法
RCT_EXPORT_METHOD(pay: (NSString *) orderInfo resolver: (RCTPromiseResolveBlock) resolve rejecter:(RCTPromiseRejectBlock) reject)
{
[[AlipaySDK defaultService] payOrder:orderInfo fromScheme:@"本app的schema" callback:^(NSDictionary *resultDic)
{
if ([@"9000" isEqualToString: [resultDic valueForKey:@"resultStatus"]]) {
resolve(@(YES));
} else {
resolve(@(NO));
}
}];
}
@end
复制代码
js层
方法导出
Alipay.ts
import {NativeModules} from 'react-native';
export interface Alipay {
pay(orderInfo: string): Promise<boolean>;
}
export const Alipay = NativeModules.AlipayModule as Alipay;
复制代码
js层使用
import Alipay from './Alipay';
try {
const result = await Alipay.pay(orderInfo);
if (result) console.log('支付成功');
} catch(e) {
console.error(e);
}
复制代码
原生模块导出相对而言还是非常简单的,在上面支付宝支付的实例中演示了导出一个简单的模块和promise在原生代码中的注入和在js层的使用。
原生js交互
原生调用js
js中调用模块代码,模块中直接导出即可,有时候我们也会需要在原生代码中去调用js的代码,例如做事件通知等。
android调用js
事件名为js层监听的名字,值可以为int、float等,与原生方法一直
reactContext.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class)
.emit("事件名", 值);
复制代码
js监听android调用
const listener = DeviceEventEmitter.addListener('事件名',
data => console.log('android调用', data));
// 调用完成移除监听
listener.remove();
复制代码
ios调用js
模块.h文件
#import <React/RCTBridgeModule.h>
#import <React/RCTEventEmitter.h>
// 修改.h中NSObject为RCTEventEmitter
@interface XXXModule : RCTEventEmitter<RCTBridgeModule>
@end
复制代码
模块.m文件
// 添加支持事件名
- (NSArray<NSString *> *)supportedEvents
{
return @[@"event1", @"event2"];
}
// 事件发送
// float body [NSNumber numberWithFloat:num]
[self sendEventWithName:@"event1" body:body];
复制代码
js监听ios调用
// 获取模块监听者
// XXXModule为模块名称,与导出的名字一致
const eventEmitter = new NativeEventEmitter(NativeModules.XXXModule);
const listener = eventEmitter.addListener('事件名',
data => console.log('ios调用', data));
// 监听完成后移除
listener.remove();
复制代码
ios和android发送事件封装方法不一样,在js层监听方法也不一样,所以需要注意平台,一般事件是在耗时操作过程中监听,在开始时候开始监听,在结束后应马上移除监听。