React Native与原生交互之跳转

举报
孔皮皮 发表于 2019/10/13 22:58:55 2019/10/13
【摘要】 React Native(简称RN)开发的app大部分都可以在JS端完成,但是也有一些复杂的功能是需要原生端来完成的,或者是在原生项目中集成RN,此时RN与原生端就不可避免的需要进行交互,比如页面跳转和数据传递。关于RN与原生更深层次的调用原理,及如何自己封装RN的原生组件,可以参考《React Native移动开发实战》(ps:白皮版)。原生跳转RN是非常简单的,本文不做讲解,本文主要分析...

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

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。