RN 开发中 难免会用到原生的一些库和方法 , 因此 RN 与 原生的数据交互 就显得很重要 。 在此整理分享一下。
原生给RN传参##
主要通过属性传值 (props)
原生端 通过向 initialProperties 中添加字典。
NSURL *jsCodeLocation = [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index.ios" fallbackResource:nil];
NSDictionary *dic = @{@"name" : @"张三"};
RCTRootView *rootView = [[RCTRootView alloc] initWithBundleURL:jsCodeLocation
moduleName:@"ReactNativeProject"
initialProperties:dic
launchOptions:launchOptions];
RN端 可以在props 里面直接获取到
import React, { Component } from 'react';
import {
AppRegistry,
View,
Title,
} from 'react-native';
class RNTestApp extends Component {
render() {
return (
<View>
<Title>{this.props.name}</Title>
</View>
);
}
}
AppRegistry.registerComponent('RNTestApp', () => RNTestApp);
RN调用原生##
1. 调用原生方法
原生端 实现 RCTBridgeModule协议,并通过RCT_EXPORT_METHOD()宏来实现方法的导出。
@interface RNTestApp ()<RCTBridgeModule>
@end
@implementation RNTestApp
RCT_EXPORT_MODULE();
RCT_EXPORT_METHOD(doSomething:(NSString *)aString withA:(NSString *)a)
{
NSLog(@"%@,%@",aString,a);
}
为了实现RCTBridgeModule协议,你的类需要包含RCT_EXPORT_MODULE()宏。你必须明确的声明要给Javascript导出的方法,否则React Native不会导出任何方法。OC中声明要给Javascript导出的方法,通过RCT_EXPORT_METHOD()宏来实现
RN 端
import React, { Component } from 'react';
import {
AppRegistry,
StyleSheet,
Text,
View,
Alert,
TouchableHighlight,
} from 'react-native';
import {
NativeModules,
NativeAppEventEmitter
} from 'react-native';
var Manager = NativeModules.RNTestApp;
class ReactNativeProject1 extends Component {
render() {
return (
<TouchableHighlight onPress={()=> Manager.doSomething('name','张三')}>
<Text style={styles.text}>点击 </Text>
</TouchableHighlight>
);
}
}
const styles = StyleSheet.create({
text: {
flex: 1,
marginTop: 55,
fontWeight: 'bold'
},
});
AppRegistry.registerComponent('ReactNativeProject1', () => ReactNativeProject);
- 需要引入 NativeModules 模块。
- NativeModules.类名.方法名 调用导出的方法。(Manager.doSomething('name','张三'))
- 桥接到Javascript的方法返回值类型必须是void。
- React Native的桥接是异步操作。
2. 对原生方法 进行回调
原生端 调用 RCTResponseSenderBlock 进行回调
// 对外提供调用方法,演示Callback
RCT_EXPORT_METHOD(testCallbackEvent:(NSDictionary *)dictionary callback:(RCTResponseSenderBlock)callback)
{
NSLog(@"当前名字为:%@",dictionary);
NSArray *events=@[@"张三 ", @"李四 ", @" 王五"];
callback(events);
}
typedef void (^RCTResponseSenderBlock)(NSArray *response);
参数只能传一个数组
import {
NativeModules,
NativeAppEventEmitter
} from 'react-native';
var Manager = NativeModules.RNTestApp;
class ReactNativeProject extends Component {
render() {
return (
<TouchableHighlight onPress={()=>{Manager.testCallbackEvent( {'name':'张三','age':'20'},
(events)=>{
this.setState({events});
}
})
}}>
<Text style={styles.text}>点击 </Text>
</TouchableHighlight>
);
}
}
原生调用RN 方法
有点通知中心的感觉 , 在原生端发送通知 , 然后RN端进行拦截。以此来调用RN端方法
- (void)calendarEventReminderReceived:(NSNotification *)notification
{
NSString *name = [notification userInfo][@"name"];
[self.bridge.eventDispatcher sendAppEventWithName:@"EventReminder"
body:@{@"name": name}];
}
import { NativeAppEventEmitter } from 'react-native';
var subscription = NativeAppEventEmitter.addListener(
'EventReminder',
(reminder) => console.log(reminder.name)
);
...
// 千万不要忘记忘记取消订阅, 通常在componentWillUnmount函数中实现。
subscription.remove();