При разработке RN связь между JS и Native обычно неразрывна, например, когда RN инициализируется, Native передает данные в JS, JS вызывает альбом Native для выбора изображений, JS вызывает модуль Native для выполнения некоторых сложных вычислений, а Native будет некоторые данные (информация GPS, гироскопы, датчики и т. д.) активно передаются в JS и т. д.
В этой статье я познакомлю вас с несколькими способами общения между JS и Native в RN, а также с их принципами и навыками использования;
Далее я расскажу о взаимодействии между JS и Native в различных сценариях.
Несколько сценариев общения:
- Native передает данные в JS при инициализации RN;
- Натив отправляет данные в JS;
- JS отправляет данные в Native;
- JS отправляет данные в Native, а затем Native возвращает данные в JS;
1. Native передает данные в JS при инициализации RN
API RN предоставляет Native способ передачи данных в JS при инициализации страницы JS.Этот способ передачи данных происходит раньше, чем другие способы передачи данных, описанные ниже.
Поскольку информации об этом методе очень мало, может быть много друзей, которые еще не знают этот метод, но это не беда.Далее я покажу вам, как использовать этот метод для передачи данных в JS.
концепция
RN позволяет указать顶级的JS 组件
передачаprops
Данные, компонент верхнего уровня можетthis.props
для получения этих данных.
iOS
[[RCTRootView alloc] initWithBundleURL: jsCodeLocation
moduleName: self.moduleName //这个"App1"名字一定要和我们在index.js中注册的名字保持一致
initialProperties:@{@"params":self.paramsInit}//RN初始化时传递给JS的初始化数据
launchOptions: nil];
Далее давайте посмотрим, какiOS
Вплоть до передачи этих данных инициализации.
iOS передает данные инициализации в RNinitialProperties
RCTRootView от RN обеспечиваетinitWithBundleURL
для рендеринга компонента JS, в этом методе укажите параметр для данных инициализации, передаваемых компоненту JS.
Прототип метода:
- (instancetype)initWithBundleURL:(NSURL *)bundleURL moduleName:(NSString *)moduleName
initialProperties:(NSDictionary *)initialProperties launchOptions:(NSDictionary *)launchOptions
-
jsCodeLocation
: путь к JS-странице RN, которую необходимо отобразить; -
moduleName
: имя загружаемого JS-модуля; -
initialProperties
: для передачи顶级JS组件
данные инициализации; -
launchOptions
: в основном используется, когда AppDelegate загружает JS Bundle, просто передайте здесь nil;
Через третий параметр вышеуказанного методаNSDictionary
Тип данных, передаваемых в顶级JS组件
.
Образец кода:
[[RCTRootView alloc] initWithBundleURL: jsCodeLocation
moduleName: self.moduleName
initialProperties:@{@"params":@"这是传递给顶级JS组件的数据"}//RN初始化时传递给JS的初始化数据
launchOptions: nil];
В приведенном выше коде мы помещаем файл с именемparams
Данные这是传递给顶级JS组件的数据
перешел к顶级的JS 组件
, затем в顶级的JS 组件
Эти данные можно получить следующими методами:
render() {
const {params}=this.props;
return (
<View style={styles.container}>
<Text style={styles.data}>来自Native初始化数据:{params}</Text>
</View>
);
}
Кроме того, если вы хотите использовать страницы не верхнего уровня, такие какCommonPage
Используя эти данные инициализации в , вы можете передать данные вCommonPage
страница:
export default class App extends Component<Props> {
...
render() {
return <CommonPage {...this.props}/>;
}
...
}
2. Собственная связь с JS (Native отправляет данные в JS)
iOS SDK RN предоставляетRCTEventEmitter
Интерфейс, через который мы можем реализовать связь от Native к JS, то есть Native передает данные в JS.
Прототип метода:
- (void)sendEventWithName:(NSString *)name body:(id)body;
Пока мы получаемRCTEventEmitter
Примеры могут быть переданы ему с помощью данных JS. чтобы достичьRCTEventEmitter
Экземпляры мы можем наследовать отRCTEventEmitter <RCTBridgeModule>
способ достижения:
DataToJSPresenter.h
/**
* React Native JS Native通信
* Author: CrazyCodeBoy
* 视频教程:https://coding.imooc.com/lesson/89.html#mid=2702
* GitHub:https://github.com/crazycodeboy
* Email:crazycodeboy@gmail.com
*/
#import <React/RCTBridgeModule.h>
#import <React/RCTEventEmitter.h>
@interface DataToJSPresenter : RCTEventEmitter <RCTBridgeModule>
@end
DataToJSPresenter.m
/**
* React Native JS Native通信
* Author: CrazyCodeBoy
* 视频教程:https://coding.imooc.com/lesson/89.html#mid=2702
* GitHub:https://github.com/crazycodeboy
* Email:crazycodeboy@gmail.com
*/
#import "DataToJSPresenter.h"
@implementation DataToJSPresenter
RCT_EXPORT_MODULE();
- (NSArray<NSString *> *)supportedEvents
{
return @[@"testData"];
}
- (instancetype)init {
if (self = [super init]) {//在module初始化的时候注册fireData广播
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(fireData:) name:@"fireData" object:nil];
}
return self;
}
- (void)fireData:(NSNotification *)notification{//发送数据给RN
NSString *eventName = notification.object[@"name"];
NSDictionary *params = notification.object[@"params"];
[self sendEventWithName:eventName body:params];
}
@end
В приведенном выше методе мы передаемRCTEventEmitter
изsendEventWithName
метод будет называтьсяeventName
Данныеparams
перешли на JS.
Подсказка: в
DataToJSPresenter
в мы достигли(NSArray<NSString *> *)supportedEvents
метод, этот метод используется для указания имени события, которое может быть отправлено в JS, поэтому оно отправляется в JS.eventName
Он должен быть настроен в этом методе, иначе он не может быть отправлен.
Шаги, необходимые для реализации связи Native to JS
Далее давайте подытожим шаги, необходимые для реализации связи между Native и JS:
- первым достичь
RCTEventEmitter <RCTBridgeModule>
; - пройти через
RCTEventEmitter
изsendEventWithName
способ передачи данных в JS;
Выполнив описанные выше шаги, мы можем запустить данные из Native в JS, так как же получить эти данные в JS?
Получить Native pass в JSRCTEventEmitter
данные отправлены
В JS вы можете пройтиNativeEventEmitter
чтобы получить Native черезRCTEventEmitter
Передаваемые данные выглядят следующим образом:
import {NativeEventEmitter} from 'react-native';
export default class CommonPage extends Component<Props> {
constructor(props) {
super(props);
this.state = {
data: "",
result: null
}
}
componentWillMount() {
this.dataToJSPresenter = new NativeEventEmitter(NativeModules.DataToJSPresenter);
this.dataToJSPresenter.addListener('testData', (e) => {// for iOS
this.setState({
data: e.data
})
})
}
componentWillUnmount() {
if (this.dataToJSPresenter){
this.dataToJSPresenter.removeListener('testData');
}
}
render() {
return (
<View style={styles.container}>
<Text style={styles.data}>收到Native的数据:{this.state.data}</Text>
</View>
);
}
}
В приведенном выше коде мы передаемNativeEventEmitter
изaddListener
Добавлен прослушиватель, который прослушивает имя, отправленное Native.testData
Данные, этоtestData
к вышеизложенномуeventName
Чтобы быть последовательным:
[self sendEventWithName:eventName body:params];
coding.IMO OC.com/lesson/89, Также…Кроме того, не забывайте вовремя удалять прослушиватель, когда компонент JS выгружается.
Вышеизложенный принцип и метод реализации связи между Native и JS в iOS.Далее давайте рассмотрим принцип и метод реализации связи между JS и Native.
3. Связь между JS и Native (JS отправляет данные в Native)
Что мы инкапсулируемNativeModuleЭто для JS. Это мост между JS и нативным общением. JS может использовать его для связи с нативом (передача данных, открытие нативных страниц и т. д.). Далее я буду использовать его дляNativeModuleДля реализации связи с JS на Native.
Вы можете узнать и сослаться на то, как реализовать NativeModuleИнкапсуляция нативной модели React Native
Первая реализация JSBridgeModule
Сначала нам нужно реализоватьRCTBridgeModule
:
JSBridgeModule.h
/**
* React Native JS Native通信
* Author: CrazyCodeBoy
* 视频教程:https://coding.imooc.com/lesson/89.html#mid=2702
* GitHub:https://github.com/crazycodeboy
* Email:crazycodeboy@gmail.com
*/
#import <React/RCTBridgeModule.h>
@interface JSBridgeModule : NSObject <RCTBridgeModule>
@end
JSBridgeModule.m
/**
* React Native JS Native通信
* Author: CrazyCodeBoy
* 视频教程:https://coding.imooc.com/lesson/89.html#mid=2702
* GitHub:https://github.com/crazycodeboy
* Email:crazycodeboy@gmail.com
*/
#import "JSBridgeModule.h"
@implementation JSBridgeModule
RCT_EXPORT_MODULE();
- (dispatch_queue_t)methodQueue
{
return dispatch_get_main_queue();//让RN在主线程回调这些方法
}
RCT_EXPORT_METHOD(sendMessage:(NSDictionary*)params){//接受RN发过来的消息
[[NSNotificationCenter defaultCenter] postNotificationName:@"sendMessage" object:params];
}
@end
Разбор кода
- существует
JSBridgeModule
, мы реализуемRCT_EXPORT_METHOD(sendMessage:(NSDictionary*)params)
метод, который в основном используется для предоставления вызовов JS для передачи данныхparams
на родной; - После получения данных пройти
NSNotificationCenter
отправлять данные в виде уведомлений;
JS вызывает JSBridgeModule для отправки данных в Native
import {NativeModules} from 'react-native';
const JSBridge = NativeModules.JSBridgeModule;
JSBridge.sendMessage({text: this.text})
С помощью приведенного выше кода я могу преобразовать данные типа Map{text: this.text}
Перешел на родной.
4. JS отправляет данные в Native, а затем Native отправляет данные обратно в JS.
через вышеуказанноеJS到Native的通信(JS发送数据给Native)
, мы реализовали связь с JS на Native, в то время мы использовалиJSBridgeModule
, на самом деле его функция этим не ограничивается, с его помощью мы также можем реализовать возврат данных из Native в JS.
Реализация в родном
существуетJSBridgeModule
Добавьте следующий метод в:
RCT_EXPORT_METHOD(doAdd:(NSInteger )num1 num2:(NSInteger )num2 resolver:(RCTPromiseResolveBlock)resolve
rejecter:(RCTPromiseRejectBlock)reject)
{
NSInteger result=num1+num2;
resolve([NSString stringWithFormat:@"%ld",(long)result]);//回调JS
}
Приведенный выше код предоставляет простую операцию сложения между двумя целыми числами для JS и возвращает результат операции в JS.Здесь мы используемRCTPromiseResolveBlock
а такжеRCTPromiseRejectBlock
Два типа обратных вызовов, представляющих успех и неудачу соответственно.
Реализация на JS
import {NativeModules} from 'react-native';
const JSBridge = NativeModules.JSBridgeModule;
JSBridge.doAdd(parseInt(this.num1), parseInt(this.num2)).then(e => {
this.setState({
result: e
})
})
В JS мы проходимJSBridge.doAdd
метод преобразует два целых числаnum1
а такжеnum2
Перешли на Native, а потом перешлиthen
Чтобы контролировать результаты возврата, весь процесс используетPromise
Метод цепного вызова.