react native 交互与原生的交互有哪些

一:原生传递参数给React Native
1:原生给React Native传参
原生给JS传数据,主要依靠属性。
通过initialProperties,这个RCTRootView的初始化函数的参数来完成。
RCTRootView还有一个appProperties属性,修改这个属性,JS端会调用相应的渲染方法。
我们使用RCTRootView将React Natvie视图封装到原生组件中。RCTRootView是一个UIView容器,承载着React Native应用。同时它也提供了一个联通原生端和被托管端的接口。
通过RCTRootView的初始化函数你可以将任意属性传递给React Native应用。参数initialProperties必须是NSDictionary的一个实例。这一字典参数会在内部被转化为一个可供JS组件调用的JSON对象。
原生oc代码:
NSURL *jsCodeL
jsCodeLocation = [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index.ios" fallbackResource:nil];
NSArray *imageList = @[@"/bar1.png",
@"/bar2.png"];
NSDictionary *wjyprops = @{@"images" : imageList};
RCTRootView *rootView = [[RCTRootView alloc] initWithBundleURL:jsCodeLocation
moduleName:@"ReactNativeProject"
initialProperties:wjyprops
launchOptions:launchOptions];
js处理代码:
'use strict';
import React, { Component } from 'react';
AppRegistry,
} from 'react-native';
class ImageBrowserApp extends Component {
renderImage(imgURI) {
&Image source={{uri: imgURI}} /&
render() {
{this.props.images.map(this.renderImage)}
AppRegistry.registerComponent('ImageBrowserApp', () =& ImageBrowserApp);
注意:不管OC中关于initialProperties的字典名字叫什么,在JS中都是this.props开头,然后接下来才是字典里面的key名字;下面是打印出来的值;
{"rootTag":1,"initialProps":{"images":["/bar1.png","/bar2.png"]}}.
2:使用appProperties进行传递,原生给React Native传参
RCTRootView同样提供了一个可读写的属性appProperties。在appProperties设置之后,React Native应用将会根据新的属性重新渲染。当然,只有在新属性和之前的属性有区别时更新才会被触发。
NSArray *imageList = @[@"/bar3.png",
@"/bar4.png"];
rootView.appProperties = @{@"images" : imageList};
你可以随时更新属性,但是更新必须在主线程中进行,读取则可以在任何线程中进行。
更新属性时并不能做到只更新一部分属性。我们建议你自己封装一个函数来构造属性。
注意:目前,最顶层的RN组件(即registerComponent方法中调用的那个)的componentWillReceiveProps和componentWillUpdateProps方法在属性更新后不会触发。但是,你可以通过componentWillMount访问新的属性值。
二:React Native执行原生的方法及回调
1:React Native执行原生的方法
.h的文件内容:
#import &Foundation/Foundation.h&
#import &RCTBridgeModule.h&
@interface wjyTestManager : NSObject&RCTBridgeModule&
注意:在React Native中,一个&原生模块&就是一个实现了&RCTBridgeModule&协议的Objective-C类,其中RCT是ReaCT的缩写。
.m的文件内容:
#import "wjyTestManager.h"
@implementation wjyTestManager
RCT_EXPORT_MODULE();
RCT_EXPORT_METHOD(doSomething:(NSString *)aString withA:(NSString *)a)
NSLog(@"%@,%@",aString,a);
注意:为了实现RCTBridgeModule协议,你的类需要包含RCT_EXPORT_MODULE()宏。这个宏也可以添加一个参数用来指定在Javascript中访问这个模块的名字。如果你不指定,默认就会使用这个Objective-C类的名字。你必须明确的声明要给Javascript导出的方法,否则React Native不会导出任何方法。OC中声明要给Javascript导出的方法,通过RCT_EXPORT_METHOD()宏来实现:
js相关代码如下:
import React, { Component } from 'react';
AppRegistry,
StyleSheet,
TouchableHighlight,
} from 'react-native';
NativeModules,
NativeAppEventEmitter
} from 'react-native';
var CalendarManager = NativeModules.wjyTestM
class ReactNativeProject extends Component {
render() {
&TouchableHighlight onPress={()=&CalendarManager.doSomething('sdfsdf','sdfsdfs')}&
&Text style={styles.text}
&点击 &/Text&
&/TouchableHighlight&
const styles = StyleSheet.create({
marginTop: 55,
fontWeight: 'bold'
AppRegistry.registerComponent('ReactNativeProject', () =& ReactNativeProject);
注意:要用到NativeModules则要引入相应的命名空间import { NativeModules } from 'react-native&;然后再进行调用CalendarManager.doSomething('sdfsdf','sdfsdfs&);桥接到Javascript的方法返回值类型必须是void。React Native的桥接操作是异步的,所以要返回结果给Javascript,你必须通过回调或者触发事件来进行。
2:传参并带有回调
对外提供调用方法,演示Callback
RCT_EXPORT_METHOD(testCallbackEvent:(NSDictionary *)dictionary callback:(RCTResponseSenderBlock)callback)
NSLog(@"当前名字为:%@",dictionary);
NSArray *events=@[@"callback ", @"test ", @" array"];
callback(@[[NSNull null],events]);
注意:第一个参数代表从JavaScript传过来的数据,第二个参数是回调方法;
JS代码如下:
NativeModules,
NativeAppEventEmitter
} from 'react-native';
var CalendarManager = NativeModules.wjyTestM
class ReactNativeProject extends Component {
render() {
&TouchableHighlight onPress={()=&{CalendarManager.testCallbackEvent(
{'name':'good','description':'http://www.lcode.org'},
(error,events)=&{
if(error){
console.error(error);
this.setState({events:events});
&Text style={styles.text}
&点击 &/Text&
&/TouchableHighlight&
3:参数类型
RCT_EXPORT_METHOD 支持所有标准JSON类型,包括:
string (NSString)
number (NSInteger, float, double, CGFloat, NSNumber)
boolean (BOOL, NSNumber)
array (NSArray) 包含本列表中任意类型
object (NSDictionary) 包含string类型的键和本列表中任意类型的值
function (RCTResponseSenderBlock)
除此以外,任何RCTConvert类支持的的类型也都可以使用(参见RCTConvert了解更多信息)。RCTConvert还提供了一系列辅助函数,用来接收一个JSON值并转换到原生Objective-C类型或类。例如
#import "RCTConvert.h"
#import "RCTBridge.h"
#import "RCTEventDispatcher.h"
对外提供调用方法,为了演示事件传入属性字段
RCT_EXPORT_METHOD(testDictionaryEvent:(NSString *)name details:(NSDictionary *) dictionary)
NSString *location = [RCTConvert NSString:dictionary[@"thing"]];
NSDate *time = [RCTConvert NSDate:dictionary[@"time"]];
NSString *description=[RCTConvert NSString:dictionary[@"description"]];
NSString *info = [NSString stringWithFormat:@"Test: %@\nFor: %@\nTestTime: %@\nDescription: %@",name,location,time,description];
NSLog(@"%@", info);
三: iOS原生访问调用React Native
如果我们需要从iOS原生方法发送数据到JavaScript中,那么使用eventDispatcher。
#import "RCTBridge.h"
#import "RCTEventDispatcher.h"
@implementation CalendarManager
@synthesize bridge = _
进行设置发送事件通知给JavaScript端
- (void)calendarEventReminderReceived:(NSNotification *)notification
NSString *name = [notification userInfo][@"name"];
[self.bridge.eventDispatcher sendAppEventWithName:@"EventReminder"
body:@{@"name": name}];
在JavaScript中可以这样订阅事件:
import { NativeAppEventEmitter } from 'react-native';
var subscription = NativeAppEventEmitter.addListener(
'EventReminder',
(reminder) =& console.log(reminder.name)
// 千万不要忘记忘记取消订阅, 通常在componentWillUnmount函数中实现。
subscription.remove();
注意:用NativeAppEventEmitter.addListener中注册一个通知,之后再OC中通过bridge.eventDispatcher sendAppEventWithName发送一个通知,这样就形成了调用关系。
四:代码段内容:
#import "CalendarManager.h"
#import "RCTConvert.h"
#import "RCTBridge.h"
#import "RCTEventDispatcher.h"
@implementation CalendarManager
@synthesize bridge=_
RCT_EXPORT_MODULE()
指定执行模块里的方法所在的队列
- (dispatch_queue_t)methodQueue
return dispatch_get_main_queue();
在完整demo中才有用到,用于更新原生UI
- (void)showInfo:(NSString *)info
更新UI操作在主线程中执行
dispatch_async(dispatch_get_main_queue(), ^{
//Update UI in UI thread here
[[NSNotificationCenter defaultCenter] postNotificationName:@"react_native_test" object:nil userInfo:@{@"info": info}];
- (void)showDate:(NSDate *)date withName:(NSString *)name forSomething:(NSString *)thing
NSDateFormatter *formatter = [[NSDateFormatter alloc] init] ;
[formatter setDateFormat:@"yyyy-MM-dd"];
NSString *info = [NSString stringWithFormat:@"Test: %@\nFor: %@\nTestTime: %@", name, thing,[formatter stringFromDate:date]];
NSLog(@"%@", info);
对外提供调用方法
RCT_EXPORT_METHOD(testNormalEvent:(NSString *)name forSomething:(NSString *)thing)
NSString *info = [NSString stringWithFormat:@"Test: %@\nFor: %@", name, thing];
NSLog(@"%@", info);
对外提供调用方法,为了演示事件时间格式化 secondsSinceUnixEpoch
RCT_EXPORT_METHOD(testDateEventOne:(NSString *)name forSomething:(NSString *)thing data:(NSNumber*)secondsSinceUnixEpoch)
NSDate *date = [RCTConvert NSDate:secondsSinceUnixEpoch];
[self showDate:date withName:name forSomething:thing];
对外提供调用方法,为了演示事件时间格式化 ISO8601DateString
RCT_EXPORT_METHOD(testDateEventTwo:(NSString *)name forSomething:(NSString *)thing date:(NSString *)ISO8601DateString)
NSDate *date = [RCTConvert NSDate:ISO8601DateString];
[self showDate:date withName:name forSomething:thing];
对外提供调用方法,为了演示事件时间格式化 自动类型转换
RCT_EXPORT_METHOD(testDateEvent:(NSString *)name forSomething:(NSString *)thing date:(NSDate *)date)
[self showDate:date withName:name forSomething:thing];
对外提供调用方法,为了演示事件传入属性字段
RCT_EXPORT_METHOD(testDictionaryEvent:(NSString *)name details:(NSDictionary *) dictionary)
NSString *location = [RCTConvert NSString:dictionary[@"thing"]];
NSDate *time = [RCTConvert NSDate:dictionary[@"time"]];
NSString *description=[RCTConvert NSString:dictionary[@"description"]];
NSString *info = [NSString stringWithFormat:@"Test: %@\nFor: %@\nTestTime: %@\nDescription: %@",name,location,time,description];
NSLog(@"%@", info);
对外提供调用方法,演示Callback
RCT_EXPORT_METHOD(testCallbackEvent:(RCTResponseSenderBlock)callback)
NSArray *events=@[@"callback ", @"test ", @" array"];
callback(@[[NSNull null],events]);
对外提供调用方法,演示Promise使用
RCT_REMAP_METHOD(testPromiseEvent,
resolver:(RCTPromiseResolveBlock)resolve
rejecter:(RCTPromiseRejectBlock)reject)
NSArray *events =@[@"Promise ",@"test ",@" array"];
if (events) {
resolve(events);
NSError *error=[NSError errorWithDomain:@"我是Promise回调错误信息..." code:101 userInfo:nil];
reject(@"no_events", @"There were no events", error);
对外提供调用方法,演示Thread使用
RCT_EXPORT_METHOD(doSomethingExpensive:(NSString *)param callback:(RCTResponseSenderBlock)callback)
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
// 在后台执行耗时操作
// You can invoke callback from any thread/queue
callback(@[[NSNull null],@"耗时操作执行完成..."]);
进行设置封装常量给JavaScript进行调用
-(NSDictionary *)constantsToExport
// 此处定义的常量为js订阅原生通知的通知名
return @{@"receiveNotificationName":@"receive_notification_test"};
开始订阅通知事件
RCT_EXPORT_METHOD(startReceiveNotification:(NSString *)name)
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(calendarEventReminderReceived:)
object:nil];
进行设置发送事件通知给JavaScript端(这里需要注意,差一个触发通知点,需自己想办法加上,或者看完整demo)
- (void)calendarEventReminderReceived:(NSNotification *)notification
NSString *name = [notification userInfo][@"name"];
[self.bridge.eventDispatcher sendAppEventWithName:@"EventReminder"
body:@{@"name": name}];
import React, { Component } from 'react';
AppRegistry,
StyleSheet,
ScrollView,
TouchableHighlight
} from 'react-native';
NativeModules,
NativeAppEventEmitter
} from 'react-native';
var CalendarManager = NativeModules.CalendarM
class CustomButton ponent {
render() {
&TouchableHighlight
style={{padding: 8, backgroundColor:this.props.backgroundColor}}
underlayColor="#a5a5a5"
onPress={this.props.onPress}&
&Text&{this.props.text}&/Text&
&/TouchableHighlight&
class ModulesDemo extends Component {
constructor(props){
super(props);
this.state={
events:'',
notice:'',
componentDidMount(){
console.log('开始订阅通知...');
this.receiveNotification();
subscription = NativeAppEventEmitter.addListener(
'EventReminder',
(reminder) =& {
console.log('通知信息:'+reminder.name)
this.setState({notice:reminder.name});
receiveNotification(){
CalendarManager.receiveNotificationName 为原生定义常量
CalendarManager.startReceiveNotification(CalendarManager.receiveNotificationName);
componentWillUnmount(){
subscription.remove();
//获取Promise对象处理
async updateEvents(){
console.log('updateEvents');
var events=await CalendarManager.testPromiseEvent();
this.setState({events});
}catch(e){
console.error(e);
render() {
var date = new Date();
&ScrollView&
&Text style={{fontSize: 16, textAlign: 'center', margin: 10}}&
&View style={{borderWidth: 1,borderColor: '#000000'}}&
&Text style={{fontSize: 15, margin: 10}}&
普通调用原生模块方法
&CustomButton text="调用testNormalEvent方法-普通"
backgroundColor= "#FF0000"
onPress={()=&CalendarManager.testNormalEvent('调用testNormalEvent方法', '测试普通调用')}
&CustomButton text="调用testDateEvent方法-日期处理"
backgroundColor= "#FF7F00"
onPress={()=&CalendarManager.testDateEvent('调用testDateEvent方法', '测试date格式',date.getTime())}
&CustomButton text="调用testDictionaryEvent方法-字典"
backgroundColor= "#FFFF00"
onPress={()=&CalendarManager.testDictionaryEvent('调用testDictionaryEvent方法', {
thing:'测试字典(字段)格式',
time:date.getTime(),
description:'就是这么简单~'
&Text style={{fontSize: 15, margin: 10}}&
'Callback返回数据:{this.state.events}
&CustomButton text="调用原生模块testCallbackEvent方法-Callback"
backgroundColor= "#00FF00"
onPress={()=&CalendarManager.testCallbackEvent((error,events)=&{
if(error){
console.error(error);
this.setState({events:events,});
&CustomButton text="调用原生模块testPromiseEvent方法-Promise"
backgroundColor= "#00FFFF"
onPress={()=&this.updateEvents()}
&View style={{borderWidth: 1,borderColor: '#000000'}}&
&Text style={{fontSize: 15, margin: 10}}&
原生调js,接收信息:{this.state.notice}
&/ScrollView&
AppRegistry.registerComponent('NativeTest', () =& ModulesDemo);
最近有个妹子弄的一个关于扩大眼界跟内含的订阅号,每天都会更新一些深度内容,在这里如果你感兴趣也可以关注一下(嘿对美女跟知识感兴趣),当然可以关注后输入:github 会有我的微信号,如果有问题你也可以在那找到我;当然不感兴趣无视此信息;
阅读(...) 评论()4544人阅读
Android(139)
React Native(11)
在前两篇的内容中,和大家分享了Android原生集成RN,以及RN的增量热更新。关于详细的内容,点击如下具体了解:
本篇内容同样和React Native 与 原生App有关,可以说更加深入了两者之间的感情,为培养下一代做出准备:React Native与原生App的通信交互。
Android系统为我们提供了webview来加载网页,为了让webview加载的网页可以与App交互,系统提供了一套机制帮助我们更方便的实现通信。同样为了实现React Native与原生App之间的通信,FB也实现了自己的一套交互机制。
(1)RCTDeviceEventEmitter 事件方式
(2)Callback 回调方式
(3)Promise
三种方式各具不同优缺点
1.RCTDeviceEventEmitter
&& 优点:可任意时刻传递,Native主导控制。
2.Callback
&& 优点:JS调用,Native返回。
&& 缺点:CallBack为异步操作,返回时机不确定
&& 优点:JS调用,Native返回。
&& 缺点:每次使用需要JS调用一次
了解了三者的通信方式,怎么能少了代码的描述!我们来看看代码如何实现。大致的实现步骤如下:
(1)定义Module类,继承ReactContextBaseJavaModule
&&&&&&&& 在Module类中,我们定义交互的方法,例如RN调用Native的方法,Native调用RN的方法等。
(2)定义Package类,继承ReactPackage
&&&&&&&& 实现Package的createNativeModules方法,将Module实例添加到集合。
(3)定义Application,继承ReactApplication
&&&&&&&& 实现getPackages方法,将Package实例添加到getPackages下的集合。
1.Module类中的核心代码
* 在rn代码里面是需要这个名字来调用该类的方法
public String getName() {
return MODULE_NAME;
&名称可以自定义,对接时协商好即可。
* RN调用Native的方法
* @param phone
@ReactMethod
public void rnCallNative(String phone) {
// 跳转到打电话界面
Intent intent = new Intent();
intent.setAction(Intent.ACTION_CALL);
intent.setData(Uri.parse(&tel:& + phone));
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); // 跳转需要添加flag, 否则报错
mContext.startActivity(intent);
& 在module中定义一个方法,并用@ReactMethod 注解标注:表明该方法会被RN调用。即被RN调用的原生方法必须使用@ReactMethod注解标注。
& 注意:RN层调用Native层进行界面跳转时,需要设置FLAG_ACTIVITY_NEW_TASK标志,否则会出现如下错误:
* Native调用RN
* @param msg
public void nativeCallRn(String msg) {
mContext.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class)
.emit(EVENT_NAME,msg);
& 上面代码定义了原生方法,通过在Android层调用RN层。使用ReactContext的getJSModule方法,emit来发送消息。同样,emit的第一个参数要与RN层中addListener方法的第一个参数相同。
2.自定义Package的核心代码
* 通信Package类
* Created by Song on .
public class CommPackage implements ReactPackage {
public CommModule mM
* 创建Native Module
* @param reactContext
public List&NativeModule& createNativeModules(ReactApplicationContext reactContext) {
List&NativeModule& modules = new ArrayList&&();
mModule = new CommModule(reactContext);
modules.add(mModule);
public List&Class&? extends JavaScriptModule&& createJSModules() {
return Collections.emptyList();
public List&ViewManager& createViewManagers(ReactApplicationContext reactContext) {
return Collections.emptyList();
&在createNativeModules方法中,初始化集合,并将module实例添加进集合,返回集合实例。
3.Application核心代码
&private static final CommPackage mCommPackage = new CommPackage();
* 获取 reactPackage
public static CommPackage getReactPackage() {
return mCommP
在getPackages方法中,将Package实例添加到Arrays中即可完成注册。以上就是Android层核心代码配置,继续来看React Native层核心代码:
1.调用原生代码
* 调用原生代码
skipNativeCall() {
let phone = '';
mModule.rnCallNative(phone);
在React Native层,通过NativeModules调用commModule,继而调用原生方法即可。注意:commModule要与Module类的getNames方法返回的名称对应。
2. 接收原生调用
* 接收原生调用
componentDidMount() {
DeviceEventEmitter.addListener('nativeCallRn',(msg)=&{
title = &React Native界面,收到数据:& +
ToastAndroid.show(&发送成功&, ToastAndroid.SHORT);
通过DeviceEventEmitter注册监听,类似于Android中的监听事件。第一个参数标识名称,要与Module中emit的Event Name相同。第二个参数即为处理回掉。
3.界面代码
render() {
&View style={styles.container}&
&Text style={styles.welcome} &
&Text style={styles.welcome} onPress={this.skipNativeCall.bind(this)}&
跳转到拨号界面
&Image source={require('./images/ic.png')} /&
在Text中注册单击事件,RN层调用原生代码,跳转到拨号界面。
4.Android层调用RN的代码
* 向RN发送消息
* @param v
public void sendMsgToRN(View v) {
Log.e(&---&,&sendMsgToRN&);
MainApplication.getReactPackage().mModule.nativeCallRn(&hello&);
调用Module中定义的nativeCallRn方法,继而出发RN层代码。以上就是通过 RCTDeviceEventEmitter 模式进行通信交互。可以很清晰的看出,交互都是以主动方式为主。
RN中剩下的两种通信方式,存在一个共同的特点:
从RN层调用Native层,Native层处理完成后,回调RN层
直接看代码实现:
(1)Callback
同样还是在Module类中定义交互方法:
* Callback 方式
* rn调用Native,并获取返回值
* @param msg
* @param callback
@ReactMethod
public void rnCallNativeFromCallback(String msg, Callback callback) {
// 1.处理业务逻辑...
String result = &处理结果:& +
// 2.回调RN,即将处理结果返回给RN
callback.invoke(result);
RN中定义回调:
* Callback 通信方式
callbackComm(msg) {
mModule.rnCallNativeFromCallback(msg,(result) =& {
ToastAndroid.show(&CallBack收到消息:& + result, ToastAndroid.SHORT);
(2)Promise
Module类中定义交互方法:
* Promise 方式
* @param msg
* @param promise
@ReactMethod
public void rnCallNativeFromPromise(String msg, Promise promise) {
Log.e(&---&,&adasdasda&);
// 1.处理业务逻辑...
String result = &处理结果:& +
// 2.回调RN,即将处理结果返回给RN
promise.resolve(result);
&RN中定义回调:
* Promise 通信方式
promiseComm(msg) {
mModule.rnCallNativeFromPromise(msg).then(
(result) =&{
ToastAndroid.show(&Promise收到消息:& + result, ToastAndroid.SHORT)
).catch((error) =&{console.log(error)});
布局中触发单击事件:
&Text style={styles.welcome} onPress={this.skipNativeCall.bind(this)}&
跳转到拨号界面
&Text style={styles.welcome} onPress={this.callbackComm.bind(this,'callback发送啦')}&
Callback通信方式
&Text style={styles.welcome} onPress={this.promiseComm.bind(this,'promise发送啦')}&
Promise通信方式
最终效果:
& Android调用React Native:
& React Native调用Android:
& 源码以上传到github,希望大家star,follow支持哦~
&&相关文章推荐
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:334353次
积分:4547
积分:4547
排名:第6795名
原创:177篇
评论:341条
阅读:3954
文章:10篇
阅读:44568
文章:27篇
阅读:92492
阅读:11137
阅读:14261
(window.slotbydup = window.slotbydup || []).push({
id: '4740881',
container: s,
size: '200,200',
display: 'inlay-fix'React Native(20)
一:原生传递参数给React Native
1:原生给React Native传参
原生给JS传数据,主要依靠属性。
通过initialProperties,这个RCTRootView的初始化函数的参数来完成。
RCTRootView还有一个appProperties属性,修改这个属性,JS端会调用相应的渲染方法。
我们使用RCTRootView将React Natvie视图封装到原生组件中。RCTRootView是一个UIView容器,承载着React
Native应用。同时它也提供了一个联通原生端和被托管端的接口。
通过RCTRootView的初始化函数你可以将任意属性传递给React Native应用。参数initialProperties必须是NSDictionary的一个实例。这一字典参数会在内部被转化为一个可供JS组件调用的JSON对象。
原生oc代码:
NSURL *jsCodeL
jsCodeLocation = [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@&index.ios& fallbackResource:nil];
NSArray *imageList = @[@&/bar1.png&,
@&/bar2.png&];
NSDictionary *wjyprops = @{@&images& : imageList};
RCTRootView *rootView = [[RCTRootView alloc] initWithBundleURL:jsCodeLocation
moduleName:@&ReactNativeProject&
initialProperties:wjyprops
launchOptions:launchOptions];
js处理代码:
'use strict';
import React, { Component } from 'react';
AppRegistry,
} from 'react-native';
class ImageBrowserApp extends Component {
renderImage(imgURI) {
&Image source={{uri: imgURI}} /&
render() {
{this.props.images.map(this.renderImage)}
AppRegistry.registerComponent('ImageBrowserApp', () =& ImageBrowserApp);
注意:不管OC中关于initialProperties的字典名字叫什么,在JS中都是this.props开头,然后接下来才是字典里面的key名字;下面是打印出来的值;
{&rootTag&:1,&initialProps&:{&images&:[&/bar1.png&,&/bar2.png&]}}.
2:使用appProperties进行传递,原生给React Native传参
RCTRootView同样提供了一个可读写的属性appProperties。在appProperties设置之后,React Native应用将会根据新的属性重新渲染。当然,只有在新属性和之前的属性有区别时更新才会被触发。
NSArray *imageList = @[@&/bar3.png&,
@&/bar4.png&];
rootView.appProperties = @{@&images& : imageList};
你可以随时更新属性,但是更新必须在主线程中进行,读取则可以在任何线程中进行。
更新属性时并不能做到只更新一部分属性。我们建议你自己封装一个函数来构造属性。
注意:目前,最顶层的RN组件(即registerComponent方法中调用的那个)的componentWillReceiveProps和componentWillUpdateProps方法在属性更新后不会触发。但是,你可以通过componentWillMount访问新的属性值。
二:React Native执行原生的方法及回调
1:React Native执行原生的方法
.h的文件内容:
#import &Foundation/Foundation.h&
#import &RCTBridgeModule.h&
@interface wjyTestManager : NSObject&RCTBridgeModule&
注意:在React Native中,一个“原生模块”就是一个实现了“RCTBridgeModule”协议的Objective-C类,其中RCT是ReaCT的缩写。
.m的文件内容:
#import &wjyTestManager.h&
@implementation wjyTestManager
RCT_EXPORT_MODULE();
RCT_EXPORT_METHOD(doSomething:(NSString *)aString withA:(NSString *)a)
NSLog(@&%@,%@&,aString,a);
注意:为了实现RCTBridgeModule协议,你的类需要包含RCT_EXPORT_MODULE()宏。这个宏也可以添加一个参数用来指定在Javascript中访问这个模块的名字。如果你不指定,默认就会使用这个Objective-C类的名字。你必须明确的声明要给Javascript导出的方法,否则React Native不会导出任何方法。OC中声明要给Javascript导出的方法,通过RCT_EXPORT_METHOD()宏来实现:
js相关代码如下:
import React, { Component } from 'react';
AppRegistry,
StyleSheet,
TouchableHighlight,
} from 'react-native';
NativeModules,
NativeAppEventEmitter
} from 'react-native';
var CalendarManager = NativeModules.wjyTestM
class ReactNativeProject extends Component {
render() {
&TouchableHighlight onPress={()=&CalendarManager.doSomething('sdfsdf','sdfsdfs')}&
&Text style={styles.text}
&点击 &/Text&
&/TouchableHighlight&
const styles = StyleSheet.create({
marginTop: 55,
fontWeight: 'bold'
AppRegistry.registerComponent('ReactNativeProject', () =& ReactNativeProject);
注意:要用到NativeModules则要引入相应的命名空间import { NativeModules } from 'react-native’;然后再进行调用CalendarManager.doSomething('sdfsdf','sdfsdfs’);桥接到Javascript的方法返回值类型必须是void。React Native的桥接操作是异步的,所以要返回结果给Javascript,你必须通过回调或者触发事件来进行。
2:传参并带有回调
对外提供调用方法,演示Callback
RCT_EXPORT_METHOD(testCallbackEvent:(NSDictionary *)dictionary callback:(RCTResponseSenderBlock)callback)
NSLog(@&当前名字为:%@&,dictionary);
NSArray *events=@[@&callback &, @&test &, @& array&];
callback(@[[NSNull null],events]);
注意:第一个参数代表从JavaScript传过来的数据,第二个参数是回调方法;
JS代码如下:
NativeModules,
NativeAppEventEmitter
} from 'react-native';
var CalendarManager = NativeModules.wjyTestM
class ReactNativeProject extends Component {
render() {
&TouchableHighlight onPress={()=&{CalendarManager.testCallbackEvent(
{'name':'good','description':'http://www.lcode.org'},
(error,events)=&{
if(error){
console.error(error);
this.setState({events:events});
&Text style={styles.text}
&点击 &/Text&
&/TouchableHighlight&
3:参数类型
RCT_EXPORT_METHOD 支持所有标准JSON类型,包括:
string (NSString)
number (NSInteger, float, double, CGFloat, NSNumber)
boolean (BOOL, NSNumber)
array (NSArray) 包含本列表中任意类型
object (NSDictionary) 包含string类型的键和本列表中任意类型的值
function (RCTResponseSenderBlock)
除此以外,任何RCTConvert类支持的的类型也都可以使用(参见RCTConvert了解更多信息)。RCTConvert还提供了一系列辅助函数,用来接收一个JSON值并转换到原生Objective-C类型或类。例如
#import &RCTConvert.h&
#import &RCTBridge.h&
#import &RCTEventDispatcher.h&
对外提供调用方法,为了演示事件传入属性字段
RCT_EXPORT_METHOD(testDictionaryEvent:(NSString *)name details:(NSDictionary *) dictionary)
NSString *location = [RCTConvert NSString:dictionary[@&thing&]];
NSDate *time = [RCTConvert NSDate:dictionary[@&time&]];
NSString *description=[RCTConvert NSString:dictionary[@&description&]];
NSString *info = [NSString stringWithFormat:@&Test: %@\nFor: %@\nTestTime: %@\nDescription: %@&,name,location,time,description];
NSLog(@&%@&, info);
三: iOS原生访问调用React Native
如果我们需要从iOS原生方法发送数据到JavaScript中,那么使用eventDispatcher。
#import &RCTBridge.h&
#import &RCTEventDispatcher.h&
@implementation CalendarManager
@synthesize bridge = _
进行设置发送事件通知给JavaScript端
- (void)calendarEventReminderReceived:(NSNotification *)notification
NSString *name = [notification userInfo][@&name&];
[self.bridge.eventDispatcher sendAppEventWithName:@&EventReminder&
body:@{@&name&: name}];
在JavaScript中可以这样订阅事件:
import { NativeAppEventEmitter } from 'react-native';
var subscription = NativeAppEventEmitter.addListener(
'EventReminder',
(reminder) =& console.log(reminder.name)
// 千万不要忘记忘记取消订阅, 通常在componentWillUnmount函数中实现。
subscription.remove();
注意:用NativeAppEventEmitter.addListener中注册一个通知,之后再OC中通过bridge.eventDispatcher
sendAppEventWithName发送一个通知,这样就形成了调用关系。
四:代码段内容:
#import &CalendarManager.h&
#import &RCTConvert.h&
#import &RCTBridge.h&
#import &RCTEventDispatcher.h&
@implementation CalendarManager
@synthesize bridge=_
RCT_EXPORT_MODULE()
指定执行模块里的方法所在的队列
- (dispatch_queue_t)methodQueue
return dispatch_get_main_queue();
在完整demo中才有用到,用于更新原生UI
- (void)showInfo:(NSString *)info
更新UI操作在主线程中执行
dispatch_async(dispatch_get_main_queue(), ^{
//Update UI in UI thread here
[[NSNotificationCenter defaultCenter] postNotificationName:@&react_native_test& object:nil userInfo:@{@&info&: info}];
- (void)showDate:(NSDate *)date withName:(NSString *)name forSomething:(NSString *)thing
NSDateFormatter *formatter = [[NSDateFormatter alloc] init] ;
[formatter setDateFormat:@&yyyy-MM-dd&];
NSString *info = [NSString stringWithFormat:@&Test: %@\nFor: %@\nTestTime: %@&, name, thing,[formatter stringFromDate:date]];
NSLog(@&%@&, info);
对外提供调用方法
RCT_EXPORT_METHOD(testNormalEvent:(NSString *)name forSomething:(NSString *)thing)
NSString *info = [NSString stringWithFormat:@&Test: %@\nFor: %@&, name, thing];
NSLog(@&%@&, info);
对外提供调用方法,为了演示事件时间格式化 secondsSinceUnixEpoch
RCT_EXPORT_METHOD(testDateEventOne:(NSString *)name forSomething:(NSString *)thing data:(NSNumber*)secondsSinceUnixEpoch)
NSDate *date = [RCTConvert NSDate:secondsSinceUnixEpoch];
[self showDate:date withName:name forSomething:thing];
对外提供调用方法,为了演示事件时间格式化 ISO8601DateString
RCT_EXPORT_METHOD(testDateEventTwo:(NSString *)name forSomething:(NSString *)thing date:(NSString *)ISO8601DateString)
NSDate *date = [RCTConvert NSDate:ISO8601DateString];
[self showDate:date withName:name forSomething:thing];
对外提供调用方法,为了演示事件时间格式化 自动类型转换
RCT_EXPORT_METHOD(testDateEvent:(NSString *)name forSomething:(NSString *)thing date:(NSDate *)date)
[self showDate:date withName:name forSomething:thing];
对外提供调用方法,为了演示事件传入属性字段
RCT_EXPORT_METHOD(testDictionaryEvent:(NSString *)name details:(NSDictionary *) dictionary)
NSString *location = [RCTConvert NSString:dictionary[@&thing&]];
NSDate *time = [RCTConvert NSDate:dictionary[@&time&]];
NSString *description=[RCTConvert NSString:dictionary[@&description&]];
NSString *info = [NSString stringWithFormat:@&Test: %@\nFor: %@\nTestTime: %@\nDescription: %@&,name,location,time,description];
NSLog(@&%@&, info);
对外提供调用方法,演示Callback
RCT_EXPORT_METHOD(testCallbackEvent:(RCTResponseSenderBlock)callback)
NSArray *events=@[@&callback &, @&test &, @& array&];
callback(@[[NSNull null],events]);
对外提供调用方法,演示Promise使用
RCT_REMAP_METHOD(testPromiseEvent,
resolver:(RCTPromiseResolveBlock)resolve
rejecter:(RCTPromiseRejectBlock)reject)
NSArray *events =@[@&Promise &,@&test &,@& array&];
if (events) {
resolve(events);
NSError *error=[NSError errorWithDomain:@&我是Promise回调错误信息...& code:101 userInfo:nil];
reject(@&no_events&, @&There were no events&, error);
对外提供调用方法,演示Thread使用
RCT_EXPORT_METHOD(doSomethingExpensive:(NSString *)param callback:(RCTResponseSenderBlock)callback)
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
// 在后台执行耗时操作
// You can invoke callback from any thread/queue
callback(@[[NSNull null],@&耗时操作执行完成...&]);
进行设置封装常量给JavaScript进行调用
-(NSDictionary *)constantsToExport
// 此处定义的常量为js订阅原生通知的通知名
return @{@&receiveNotificationName&:@&receive_notification_test&};
开始订阅通知事件
RCT_EXPORT_METHOD(startReceiveNotification:(NSString *)name)
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(calendarEventReminderReceived:)
object:nil];
进行设置发送事件通知给JavaScript端(这里需要注意,差一个触发通知点,需自己想办法加上,或者看完整demo)
- (void)calendarEventReminderReceived:(NSNotification *)notification
NSString *name = [notification userInfo][@&name&];
[self.bridge.eventDispatcher sendAppEventWithName:@&EventReminder&
body:@{@&name&: name}];
import React, { Component } from 'react';
AppRegistry,
StyleSheet,
ScrollView,
TouchableHighlight
} from 'react-native';
NativeModules,
NativeAppEventEmitter
} from 'react-native';
var CalendarManager = NativeModules.CalendarM
class CustomButton ponent {
render() {
&TouchableHighlight
style={{padding: 8, backgroundColor:this.props.backgroundColor}}
underlayColor=&#a5a5a5&
onPress={this.props.onPress}&
&Text&{this.props.text}&/Text&
&/TouchableHighlight&
class ModulesDemo extends Component {
constructor(props){
super(props);
this.state={
events:'',
notice:'',
componentDidMount(){
console.log('开始订阅通知...');
this.receiveNotification();
subscription = NativeAppEventEmitter.addListener(
'EventReminder',
(reminder) =& {
console.log('通知信息:'+reminder.name)
this.setState({notice:reminder.name});
receiveNotification(){
CalendarManager.receiveNotificationName 为原生定义常量
CalendarManager.startReceiveNotification(CalendarManager.receiveNotificationName);
componentWillUnmount(){
subscription.remove();
//获取Promise对象处理
async updateEvents(){
console.log('updateEvents');
var events=await CalendarManager.testPromiseEvent();
this.setState({events});
}catch(e){
console.error(e);
render() {
var date = new Date();
&ScrollView&
&Text style={{fontSize: 16, textAlign: 'center', margin: 10}}&
&View style={{borderWidth: 1,borderColor: '#000000'}}&
&Text style={{fontSize: 15, margin: 10}}&
普通调用原生模块方法
&CustomButton text=&调用testNormalEvent方法-普通&
backgroundColor= &#FF0000&
onPress={()=&CalendarManager.testNormalEvent('调用testNormalEvent方法', '测试普通调用')}
&CustomButton text=&调用testDateEvent方法-日期处理&
backgroundColor= &#FF7F00&
onPress={()=&CalendarManager.testDateEvent('调用testDateEvent方法', '测试date格式',date.getTime())}
&CustomButton text=&调用testDictionaryEvent方法-字典&
backgroundColor= &#FFFF00&
onPress={()=&CalendarManager.testDictionaryEvent('调用testDictionaryEvent方法', {
thing:'测试字典(字段)格式',
time:date.getTime(),
description:'就是这么简单~'
&Text style={{fontSize: 15, margin: 10}}&
'Callback返回数据:{this.state.events}
&CustomButton text=&调用原生模块testCallbackEvent方法-Callback&
backgroundColor= &#00FF00&
onPress={()=&CalendarManager.testCallbackEvent((error,events)=&{
if(error){
console.error(error);
this.setState({events:events,});
&CustomButton text=&调用原生模块testPromiseEvent方法-Promise&
backgroundColor= &#00FFFF&
onPress={()=&this.updateEvents()}
&View style={{borderWidth: 1,borderColor: '#000000'}}&
&Text style={{fontSize: 15, margin: 10}}&
原生调js,接收信息:{this.state.notice}
&/ScrollView&
AppRegistry.registerComponent('NativeTest', () =& ModulesDemo);
&&相关文章推荐
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:78011次
积分:1450
积分:1450
排名:千里之外
原创:59篇
转载:45篇
(5)(1)(2)(3)(1)(5)(4)(18)(7)(5)(16)(12)(12)(12)(1)
(window.slotbydup = window.slotbydup || []).push({
id: '4740881',
container: s,
size: '200,200',
display: 'inlay-fix'

我要回帖

更多关于 reactnative与oc交互 的文章

 

随机推荐