最近开始入手了React-Native的开发,先说一下RN开发的优点
- 包含了iOS和Android两个端
- 开发速度快
- 提供热更新方法,逃避苹果审核
我不是纯RN开发,但就最后一个原因(第二个原因也算是,不过对于不是纯RN开发的,开发起来也不是很快),让我不得不对RN的开发产生了兴趣。因为我主要做iOS的,所以接下来说的原生与RN的交互主要以iOS为主.
RN传值给原生界面
1.在xcode中建立交互的bridge文件
- 新建一个继承与NSObject类的PushNative文件,在PushNative.h中导入相关类和实现协议RCTBridgeModule
1 | #import <React/RCTBridgeModule.h> |
- PushNative.m配置,为了实现该协议,需要含有一个宏:RCT_EXPORT_MODULE()
1 | #import "PushNative.h" |
- 在react-native中,我们用组件NativeModules来实现传输和接受消息
1 | import React, { Component } from 'react'; |
- 这时候在iOS代码里,写接收消息的方法
1 | RCT_EXPORT_METHOD(addEventWithString:(NSString *)string Detail:(NSDictionary *)dic) { |
- 在RN中,写发送的代码,通过myPush获取iOS代码中接收的方法
1 | <Text style={styles.instructions} onPress={() => { |
运行,点击show detail,即将RN中的值传到了原生界面中。
原生传值给RN
1.回调
还是在PushNative.m中,对外提供调用方法
1 | RCT_EXPORT_METHOD(TestWithCallBackOne:(NSString *)string callBack:(RCTResponseSenderBlock)callBack) { |
在RN中,通过Push找到TestWithCallBackOne方法,并给原生界面传了个值
1 | callBackArray = () => { |
在点击按钮出调用callBackArray,运行后,点击按钮,会弹出提示框”1“。
2.constantsToExport
在iOS中实现协议RCTBridgeModule的方法constantsToExport
1 | //原生模块可以导出一些常量,这些常量在JavaScript端随时都可以访问。用这种方法来传递一些静态数据,可以避免通过bridge进行一次来回交互。 |
在RN中可以直接通过Push找到customDicKey这个key,很牛b。
1 | <Text style={styles.instructions} onPress={() =>{ |
运行,点击按钮提示”this is customDic“。
RN跳转原生界面
1.首先需要在iOS的appdelegate中,在.h中设置个控制器的对象
1 | @property (nonatomic, strong) UIViewController *rootViewController; |
然后在.m中将window的根视图设置为.h中的那个控制器对象
1 | self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds]; |
接下来,RN跳转原生界面,和RN传值给原生界面方法差不多,都是需要一个brige文件,和上面那个PushNative一样,都是在里面写接收方法,这里也叫做跳转方法,不过跳转的代码要写入主线程中,否则会有问题。
1 | RCT_EXPORT_METHOD(RNOpenOneVC){ |
在这里,我是模态进入原生界面的,所以原生界面没有导航栏,我在这里给新创建的要跳转的界面TestController创了一个导航栏。另外,需要传值的话,在方法名RNOpenOneVC后面用括号传值即可,我在这里去掉了。
在RN中,直接通过push找到方法RNOpenOneVC即可
1 | <Text style={styles.instructions} onPress={() => { |
很简单吧,其实和传值基本一样。
原生界面跳转RN界面
原生跳RN界面,和appdelgate里面帮我们写好的基本一样,你只需要在要跳转的地方执行下面代码
1 | NSURL *jsCodeLocation; |
其中rBundleRoot指向RN中的index.js文件,这时候就有一个新的问题来了,一个RN程序只有一个index.js文件,如果我在原生多个界面要跳转不同的RN界面怎么办呢?
不同原生界面跳转不同RN界面
在iOS程序中,需要针对Properties设置不同的值,用来区分是什么界面.
1 | NSURL *jsCodeLocation; |
如上,我要跳详情界面,在点击方法处设置原生跳RN界面,传了个属性为PageTwo。
然后在RN中,设置路由,因为每个RN程序的指定入口只能有一个,一般默认是index.js文件,而它是指向App.js文件的,我们就在App.js文件中布局做区分.
1 | export default class App extends Component<Props> { |
这样就实现了跳转RN的时候会根据不同的属性值来渲染不同的界面.
原生给RN发送通知
原生发送通知给RN,首先肯定是在bridge文件中发送通知,在这里还是以上面的PushNative文件为例
在.h文件中导入框架React/RCTEventEmitter.h,并让PushNative继承于RCTEventEmitter
1 | #import <Foundation/Foundation.h> |
然后分别实现两个代理方法
1 | #pragma mark -- 发送通知 |
上面的senderNotification方法,是我们原生在需要用到的地方发送通知的方法,原生中监听原生的通知是在PushNative的初始化方法里
1 | - (instancetype)init { |
在需要的地方发送本地通知
1 | [[NSNotificationCenter defaultCenter] postNotificationName:@"jumpDetail" object:nil]; |
总的模式就是:原生发送本地通知-> 本地监听通知->bridge发送通知。
然后就到RN那边去监听通知即可.
1 | //拿到原生模块 |
1 | componentDidMount() { |