十年網(wǎng)站開發(fā)經(jīng)驗 + 多家企業(yè)客戶 + 靠譜的建站團隊
量身定制 + 運營維護+專業(yè)推廣+無憂售后,網(wǎng)站問題一站解決
簡介

超過十多年行業(yè)經(jīng)驗,技術領先,服務至上的經(jīng)營模式,全靠網(wǎng)絡和口碑獲得客戶,為自己降低成本,也就是為客戶降低成本。到目前業(yè)務范圍包括了:成都網(wǎng)站設計、成都網(wǎng)站建設、外貿網(wǎng)站建設,成都網(wǎng)站推廣,成都網(wǎng)站優(yōu)化,整體網(wǎng)絡托管,成都微信小程序,微信開發(fā),成都app軟件開發(fā),同時也可以讓客戶的網(wǎng)站和網(wǎng)絡營銷和我們一樣獲得訂單和生意!
如果你看的這一篇,需要你對ReactNative的開發(fā)有一定的了解,此文講的是在ReactNative提供的組件不能滿足需求,或者native用于較成熟的組件想要輸出,那么就需要用到自定義組件了.
通過該文,我們也可以對native和JS交互方式進行初步了解,關于輸出方法內部實現(xiàn),我們下一篇再剖.
Native module
native module就是實現(xiàn)了RCTBridgeModule協(xié)議的OC類.RCT就是ReaCT的縮寫.
具體步驟如下
#import 類,然后遵守RCTBridgeModule協(xié)議.RCT_EXPORT_MODULE(customName)方法. customName是自定義的組件名,如果不填默認為當前類名.這個組件名是用于向JS輸出.輸出組建后,默認不會向JS輸出任何方法,想要輸出方法,需要自定義實現(xiàn)方法輸出,使用宏RCT_EXPORT_METHOD ()
RCT_EXPORT_METHOD(addEvent:(NSString *)name location:(NSString *)location)
{
RCTLogInfo(@"Pretending to create an event %@ at %@", name, location);
}對于JS端,調用時就可以如下
import {NativeModules} from 'react-native';
var CustomName = NativeModules.CalendarManager;
CustomName.addEvent('Birthday Party', '4 Privet Drive, Surrey');注意
向JS輸出的方法名,是RCT_EXPORT_METHOD之后,第一個冒號之前的名字.如果native已經(jīng)暴露了多個冒號之前同名的方法,RN提供了RCT_REMAP_METHOD ()來制定方法名.
另外一點, RCT_EXPORT_METHOD回調進入的方法,默認并不在主線程,如果想要進行主線程的方法調用,需要手動進行dispatch_async(dispatch_get_main_queue(), ^{});回到主線程
RCT_EXPORT_METHOD參數(shù)
RCT_EXPORT_METHOD支持如下的參數(shù)類型
也支持所有RCTConvert支持的類型.
回調
native module支持回調類型RCTResponseSenderBlock
RCT_EXPORT_METHOD(findEvents:(RCTResponseSenderBlock)callback)
{
NSArray *events = ...
callback(@[[NSNull null], events]);
}RCTResponseSenderBlock只支持一個參數(shù):一個包含了多個參數(shù)的數(shù)組.在JS端可以如下,默認第一個參數(shù)是error.當沒有錯誤時error為空.
CalendarManager.findEvents((error, events) => {
if (error) {
console.error(error);
} else {
this.setState({events: events});
}
});native module只能調用一次回調.如果想傳遞錯誤,通過RCTUtils.h類中的RCTMakeError來創(chuàng)建.
Promise
Promise是用于實現(xiàn)異步操作async/await的工具類.如果最后一個參數(shù)類型為RCTPromiseResolveBlock和RCTPromiseRejectBlock,JS端會返回一個promise對象,進行一步操作.
RCT_REMAP_METHOD(findEvents,
findEventsWithResolver:(RCTPromiseResolveBlock)resolve
rejecter:(RCTPromiseRejectBlock)reject)
{
NSArray *events = ...
if (events) {
resolve(events);
} else {
NSError *error = ...
reject(@"no_events", @"There were no events", error);
}
}JS端因為獲取的是promise對象,可以使用await關鍵字進行異步調用并等待結果
async function updateEvents() {
try {
var events = await CalendarManager.findEvents();
this.setState({events});
} catch (e) {
console.error(e);
}
}
updateEvents();關于線程
JS執(zhí)行native module是在一個單獨的線程實現(xiàn)的,可以通過- (dispatch_queue_t)methodQueue來控制.如果返回主線程,所有執(zhí)行的方法會在主線程被執(zhí)行.
- (dispatch_queue_t)methodQueue
{
return dispatch_get_main_queue();
}方法methodQueue之后在組件初始化時被調用一次.
輸出實例
除了可以輸出方法,還有輸出實例.
- (NSDictionary *)constantsToExport
{
return @{ @"firstDayOfTheWeek": @"Monday" };
}在JS端可以直接獲取console.log(CalendarManager.firstDayOfTheWeek);
只有在初始化時實例輸出才是有效的,如果在運行時修改constantsToExport是不會影響JS環(huán)境的數(shù)據(jù)的.
輸出枚舉
通過typedef NS_ENUM()定義的枚舉,可以通過增加RCTConvert的擴展來完成
@implementation RCTConvert (StatusBarAnimation)
RCT_ENUM_CONVERTER(UIStatusBarAnimation, (@{ @"statusBarAnimationNone" : @(UIStatusBarAnimationNone),
@"statusBarAnimationFade" : @(UIStatusBarAnimationFade),
@"statusBarAnimationSlide" : @(UIStatusBarAnimationSlide)}),
UIStatusBarAnimationNone, integerValue)
@end之后就可以通過輸出屬性和方法等方式在JS中使用了.
native向JS發(fā)方法
想給JS發(fā)方法,可以繼承類RCTEventEmitter,實現(xiàn)supportedEvents方法,然后通過調用self sendEventWithName:即可.
RCT_EXPORT_MODULE(); - (NSArray*)supportedEvents { return @[@"EventReminder"]; } - (void)calendarEventReminderReceived:(NSNotification *)notification { NSString *eventName = notification.userInfo[@"name"]; [self sendEventWithName:@"EventReminder" body:@{@"name": eventName}]; }
JS端可以通過NativeEventEmitter進行注冊和調用
import { NativeEventEmitter, NativeModules } from 'react-native';
const { CalendarManager } = NativeModules;
const calendarManagerEmitter = new NativeEventEmitter(CalendarManager);
const subscription = calendarManagerEmitter.addListener(
'EventReminder',
(reminder) => console.log(reminder.name)
);
...
// Don't forget to unsubscribe, typically in componentWillUnmount
subscription.remove();注意取消訂閱,一般在componentWillUnmount內執(zhí)行.
客戶端可以通過一些方式獲取JS注冊和移除訂閱的事件,來優(yōu)化只在有訂閱者的情況下才發(fā)送事件.
// Will be called when this module's first listener is added.
-(void)startObserving {
hasListeners = YES;
// Set up any upstream listeners or background tasks as necessary
}
// Will be called when this module's last listener is removed, or on dealloc.
-(void)stopObserving {
hasListeners = NO;
// Remove upstream listeners, stop unnecessary background tasks
}資料
native modules官文
總結
以上就是這篇文章的全部內容了,希望本文的內容對大家的學習或者工作具有一定的參考學習價值,如果有疑問大家可以留言交流,謝謝大家對創(chuàng)新互聯(lián)的支持。