React Native与原生交互之跳转
React Native(简称RN)开发的app大部分都可以在JS端完成,但是也有一些复杂的功能是需要原生端来完成的,或者是在原生项目中集成RN,此时RN与原生端就不可避免的需要进行交互,比如页面跳转和数据传递。
关于RN与原生更深层次的调用原理,及如何自己封装RN的原生组件,可以参考《React Native移动开发实战》(ps:白皮版)。原生跳转RN是非常简单的,本文不做讲解,本文主要分析其他的运用场景。
RN跳转原生页面
使用“react-native init”命令创建一个RN项目,新创建的项目包含了android和iOS的原生项目,如果有原生的代码可以在原生项目中编写,RN的代码则单独放到相应的JS文件中。从RN跳转到原生,其实是在原生端创建Module类通过桥接的方式导出到JS端供JS代码调用原生端代码来实现的。
跳转到Android原生
对于Android平台来说,要完成RN跳转到Android原生的功能,主要会涉及以下几个步骤:
1. 定义Module类,该类继承ReactContextBaseJavaModule
在Module类中,重写getName方法声明Module类名称,创建相关方法用来做页面跳转。
public class OpenNativeModule extends ReactContextBaseJavaModule { private ReactContext mReactContext; public OpenNativeModule(ReactApplicationContext context) { super(context); this.mReactContext = context; } @Override public String getName() { return "OpenNativeModule"; } //打开登录设置界面,用于给RN调用 @ReactMethod public void openNativeVC() { Intent intent = new Intent(); intent.setClass(mReactContext, SettingsActivity.class); intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); mReactContext.startActivity(intent); } }
2. 定义Package类,实现接口ReactPackage。
Package类需要实现createNativeModules和createViewManagers两个方法,在createNativeModules中初始化Module类并添加到集合。
public class TestReactPackage implements ReactPackage { @Override public List createNativeModules( ReactApplicationContext reactContext) { List modules = new ArrayList<>(); modules.add(new OpenNativeModule(reactContext)); return modules; } @Override public List createViewManagers(ReactApplicationContext reactContext) { return Collections.emptyList(); } }
3. 定义Application类,继承android的Application,并实现ReactApplication接口。
每一个自定义的Package都需要添加到Application注册。在getPackages方法中初始化Package类,并添加到集合。
protected List getPackages() { return Arrays.asList( new OpenNativePackage() ); }
跳转到iOS原生
相比Android,iOS的实现就相对简单得多,只需要创建一个Module类,实现RCTBridgeModule协议即可。涉及到的代码有:
OpenNativeModule.h
#import #import @interface OpenNativeModule : NSObject@end1234567
OpenNativeModule.m
#import "OpenNativeModule.h" #import "AppDelegate.h" #import "NativeViewController.h" @implementation OpenNativeModuleRCT_EXPORT_MODULE(); RCT_EXPORT_METHOD(openNativeVC) { dispatch_async(dispatch_get_main_queue(), ^{ AppDelegate *delegate = (AppDelegate *)([UIApplication sharedApplication].delegate); UINavigationController *rootNav = delegate.navController; NativeViewController *nativeVC = [[NativeViewController alloc] init]; [rootNav pushViewController:nativeVC animated:YES]; }); }@end
然后,在RN中跳转的时候通过NativeModules.OpenNativeModule对象,然后就可以跳转了。例如:
import React from 'react'; import {View, Text, Button, NativeModules} from 'react-native'; var nativeModule = NativeModules.OpenNativeModule; export default class HomeScreen extends React.Component { render() { return ( { this.jumpToNativeView(); }}/> ) } jumpToNativeView() { nativeModule.openNativeVC(); } }
Native跳转到RN
Android
对于Android来说,原本的启动页面是MainActivity, MainActivity就对应着RN页面。 我创建了一个LaunchActivity作为启动页面,在AndroidManifest.xml中将其设置为启动页。在LaunchActivity中添加一个button,设置点击跳转到MainActivity就完成了原生页面到RN的跳转,是不是很简单?
public class LaunchActivity extends AppCompatActivity { private Button button; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_launch); button = (Button) findViewById(R.id.button); button.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Intent intent = new Intent(LaunchActivity.this, MainActivity.class); startActivity(intent); } }); } }
ios
iOS端也一样,RN页面的初始化是在AppDelegate中完成的,这里我们将window的rootViewController改为原生的UIViewController。
@implementation AppDelegate- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds]; _navController = [[UINavigationController alloc] initWithRootViewController:[[HomeViewController alloc] init]]; self.window.rootViewController = _navController; [self.window makeKeyAndVisible]; return YES; }@end
在HomeViewController中创建一个button,点击button跳转到RNViewController。
@implementation HomeViewController- (void)viewDidLoad { [super viewDidLoad]; self.title = @"这是iOS原生页面"; self.view.backgroundColor = [UIColor brownColor]; UIButton *button = [[UIButton alloc] initWithFrame:CGRectMake(100, 100, 200, 50)]; [button setTitle:@"点击跳转到RN页面" forState:UIControlStateNormal]; [button addTarget:self action:@selector(onClickButton) forControlEvents:UIControlEventTouchUpInside]; [self.view addSubview:button]; } - (void)onClickButton { RNViewController *vc = [[RNViewController alloc] init]; [self.navigationController pushViewController:vc animated:YES]; }
AppDelegate中RN页面的初始化操作放到RNViewController中来。涉及的代码如下:
@implementation RNViewController- (void)viewDidLoad { [super viewDidLoad]; self.title = @"这是RN页面"; NSURL *jsCodeLocation; jsCodeLocation = [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index" fallbackResource:nil]; RCTRootView *rootView = [[RCTRootView alloc] initWithBundleURL:jsCodeLocation moduleName:@"NativeJumpToRN" initialProperties:nil launchOptions:nil]; rootView.backgroundColor = [[UIColor alloc] initWithRed:1.0f green:1.0f blue:1.0f alpha:1]; self.view = rootView; }
到此,原生页面向RN的跳转就算完成了。
本文转载自异步社区
原文链接:https://www.epubit.com/articleDetails?id=Nf5c2f4e7-1d1e-44f6-aa5e-6e4daf174bf9
- 点赞
- 收藏
- 关注作者
评论(0)