RN и нативное взаимодействие (1) — базовый переход на страницу

внешний интерфейс JavaScript Android iOS React Native

Большая часть процесса разработки приложения React Native (далее RN) может быть выполнена на стороне JS, но есть также некоторые функции, которые необходимо выполнить на стороне натива. В это время RN и собственный конец неизбежно должны взаимодействовать, например переходить на другую страницу и передавать данные. В этой статье в основном используется RN — native, native — RN — native в качестве примера, чтобы объяснить, как выполнять основные операции перехода на страницу.

Что касается перехода по страницам, я написал три демонстрации. Отправить адрес сюда:

RNAddNativeа такжеRNPushToNativeПочти страница RN переходит к собственному экземпляру, разница заключается вRNAddNativeиспользовалreact-native-navigation,RNPushToNativeиспользовалreact-navigation. Попробовав обе навигационные библиотеки, я предпочитаю использоватьreact-native-navigation,Кто знает.

NativeJumpToRNЭто пример нативной страницы, переходящей на RN, а затем с RN на нативную.

В реальной разработке, я думаю, лучше разделить RN-страницы (написанные на JS) и нативные страницы (написанные под iOS и Android), а общие страницы все равно реализуются с помощью RN, каждая из которых нуждается в настройке и имеет сложные функции. Страница по-прежнему написана нативно. Старайтесь не встраивать RN и нативные компоненты, ведь писать UI-компоненты относительно просто, нет необходимости встраивать RN-страницу как компонент в нативную страницу или нативный компонент в RN-страницу. Разделяйте их и при необходимости переходите напрямую между страницами, что также удобно для обработки.

РН — родной

Если вы еще не создали нативный проект, просто перейдите прямоreact-native initСоздайте проект RN, и проекты Android и iOS будут созданы для вас автоматически. Проекты для Android и iOS можно разрабатывать независимо друг от друга, и RN не повлияет на них. Если у вас уже есть нативный проект, поищите, как интегрировать React Native в существующий нативный проект. Чтобы упростить пространство, я не буду здесь вдаваться в подробности.

кRNPushToNativeВ качестве примера давайте сначала объясним, как перейти с RN на нативную страницу. Переход от RN к нативному на самом деле достигается путем создания класса модуля на нативной стороне и его экспорта на сторону JS путем связывания кода JS для вызова нативного кода.

Android

Android в три шага:

1. Определите класс модуля, наследуйтеReactContextBaseJavaModule

В классе модуля переопределите метод getName, чтобы объявить имя класса модуля, и создайте собственный метод для перехода по страницам.

2. Определите класс Package и реализуйте интерфейсReactPackage

Класс пакета должен реализоватьcreateNativeModulesа такжеcreateViewManagersдва метода. существуетcreateNativeModulesИнициализируйте класс модуля и добавьте его в коллекцию.

3. Определите класс приложения, наследуйте приложение Android и реализуйте интерфейс ReactApplication.

Класс Package инициализируется в методе getPackages и добавляется в коллекцию.

При создании проекта RN класс Application уже существует, поэтому нет необходимости создавать его снова. Если он интегрирован в существующий собственный проект, вам необходимо вручную изменить класс приложения.

Основной код класса модуля:

public class OpenNativeModule extends ReactContextBaseJavaModule {

    private ReactContext mReactContext;

    public OpenNativeModule(ReactApplicationContext context) {
        super(context);
        this.mReactContext = context;
    }

    @Override
    public String getName() {
        return "OpenNativeModule";
    }

    @ReactMethod
    public void openNativeVC() {
        Intent intent = new Intent();
        intent.setClass(mReactContext, SettingsActivity.class);
        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        mReactContext.startActivity(intent);
    }
}

Основной код класса пакета:

public class TestReactPackage implements ReactPackage {

    @Override
    public List<NativeModule> createNativeModules(
            ReactApplicationContext reactContext) {
        List<NativeModule> modules = new ArrayList<>();
        modules.add(new OpenNativeModule(reactContext));
        return modules;
    }

    @Override
    public List<ViewManager> createViewManagers(ReactApplicationContext reactContext) {
        return Collections.emptyList();
    }
}

Основной код класса приложения:

@Override
    protected List<ReactPackage> getPackages() {
      return Arrays.<ReactPackage>asList(
          new MainReactPackage(),
          new VectorIconsPackage(),
          new TestReactPackage()
      );
    }

iOS

Сторона iOS намного проще, чем Android, вам нужно только создать класс Module и реализовать протокол RCTBridgeModule.

OpenNativeModule.hКод:

#import <Foundation/Foundation.h>
#import <React/RCTBridgeModule.h>

@interface OpenNativeModule : NSObject<RCTBridgeModule>

@end

OpenNativeModule.mКод:

#import "OpenNativeModule.h"
#import "AppDelegate.h"
#import "NativeViewController.h"

@implementation OpenNativeModule

RCT_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:

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 (
      <View>
        <Text>首页</Text>
        <Button title={'跳转到原生页面'} onPress={() => {
          this.jumpToNativeView();
        }}/>
      </View>
    )
  }
  
  jumpToNativeView() {
    nativeModule.openNativeVC();
  }
}

Собственный — RN — Собственный

Собственный переход к RN, а затем RN для перехода к собственной странице, этот пример может относиться кNativeJumpToRN. Переход с RN на натив осуществляется по тому же принципу, что и выше, отличие заключается в переходе с натива на RN. В этой демонстрации я просто изменил начальную страницу собственного проекта со страницы RN на собственную страницу и встроил исходную страницу RN в собственную страницу.

Для Android исходная страница-заставкаMainActivity, MainActivityСоответствует странице RN. я создалLaunchActivityВ качестве стартовой страницы наAndroidManifest.xmlустановить его в качестве стартовой страницы. существуетLaunchActivityДобавьте кнопку к кнопке, установите щелчок для перехода кMainActivityПрыжок с родной страницы на РН завершен, не правда ли, очень просто?

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.Инициализация страницы RN在AppDelegateзавершено в , здесь мы будемrootViewControllerизменить на роднойUIViewController.AppDelegateОсновной код:

@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Создайте кнопку в , нажмите кнопку, чтобы перейти к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];
}

@end

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 завершен.