React Native自定義組件與輸出方法詳解
簡(jiǎn)介
如果你看的這一篇,需要你對(duì)ReactNative的開(kāi)發(fā)有一定的了解,此文講的是在ReactNative提供的組件不能滿(mǎn)足需求,或者native用于較成熟的組件想要輸出,那么就需要用到自定義組件了.
通過(guò)該文,我們也可以對(duì)native和JS交互方式進(jìn)行初步了解,關(guān)于輸出方法內(nèi)部實(shí)現(xiàn),我們下一篇再剖.
Native module
native module就是實(shí)現(xiàn)了RCTBridgeModule協(xié)議的OC類(lèi).RCT就是ReaCT的縮寫(xiě).
具體步驟如下
- 引入
#import <React/RCTBridgeModule.h>類(lèi),然后遵守RCTBridgeModule協(xié)議. - 實(shí)現(xiàn)
RCT_EXPORT_MODULE(customName)方法. customName是自定義的組件名,如果不填默認(rèn)為當(dāng)前類(lèi)名.這個(gè)組件名是用于向JS輸出.
輸出組建后,默認(rèn)不會(huì)向JS輸出任何方法,想要輸出方法,需要自定義實(shí)現(xiàn)方法輸出,使用宏RCT_EXPORT_METHOD ()
RCT_EXPORT_METHOD(addEvent:(NSString *)name location:(NSString *)location)
{
RCTLogInfo(@"Pretending to create an event %@ at %@", name, location);
}
對(duì)于JS端,調(diào)用時(shí)就可以如下
import {NativeModules} from 'react-native';
var CustomName = NativeModules.CalendarManager;
CustomName.addEvent('Birthday Party', '4 Privet Drive, Surrey');
注意
向JS輸出的方法名,是RCT_EXPORT_METHOD之后,第一個(gè)冒號(hào)之前的名字.如果native已經(jīng)暴露了多個(gè)冒號(hào)之前同名的方法,RN提供了RCT_REMAP_METHOD ()來(lái)制定方法名.
另外一點(diǎn), RCT_EXPORT_METHOD回調(diào)進(jìn)入的方法,默認(rèn)并不在主線(xiàn)程,如果想要進(jìn)行主線(xiàn)程的方法調(diào)用,需要手動(dòng)進(jìn)行dispatch_async(dispatch_get_main_queue(), ^{});回到主線(xiàn)程
RCT_EXPORT_METHOD參數(shù)
RCT_EXPORT_METHOD支持如下的參數(shù)類(lèi)型
- string (NSString)
- number (NSInteger, float, double, CGFloat, NSNumber)
- boolean (BOOL, NSNumber)
- array (NSArray) of any types from this list
- object (NSDictionary) with string keys and values of any type from this list
- function (RCTResponseSenderBlock)
也支持所有RCTConvert支持的類(lèi)型.
回調(diào)
native module支持回調(diào)類(lèi)型RCTResponseSenderBlock
RCT_EXPORT_METHOD(findEvents:(RCTResponseSenderBlock)callback)
{
NSArray *events = ...
callback(@[[NSNull null], events]);
}
RCTResponseSenderBlock只支持一個(gè)參數(shù):一個(gè)包含了多個(gè)參數(shù)的數(shù)組.在JS端可以如下,默認(rèn)第一個(gè)參數(shù)是error.當(dāng)沒(méi)有錯(cuò)誤時(shí)error為空.
CalendarManager.findEvents((error, events) => {
if (error) {
console.error(error);
} else {
this.setState({events: events});
}
});
native module只能調(diào)用一次回調(diào).如果想傳遞錯(cuò)誤,通過(guò)RCTUtils.h類(lèi)中的RCTMakeError來(lái)創(chuàng)建.
Promise
Promise是用于實(shí)現(xiàn)異步操作async/await的工具類(lèi).如果最后一個(gè)參數(shù)類(lèi)型為RCTPromiseResolveBlock和RCTPromiseRejectBlock,JS端會(huì)返回一個(gè)promise對(duì)象,進(jìn)行一步操作.
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端因?yàn)楂@取的是promise對(duì)象,可以使用await關(guān)鍵字進(jìn)行異步調(diào)用并等待結(jié)果
async function updateEvents() {
try {
var events = await CalendarManager.findEvents();
this.setState({events});
} catch (e) {
console.error(e);
}
}
updateEvents();
關(guān)于線(xiàn)程
JS執(zhí)行native module是在一個(gè)單獨(dú)的線(xiàn)程實(shí)現(xiàn)的,可以通過(guò)- (dispatch_queue_t)methodQueue來(lái)控制.如果返回主線(xiàn)程,所有執(zhí)行的方法會(huì)在主線(xiàn)程被執(zhí)行.
- (dispatch_queue_t)methodQueue
{
return dispatch_get_main_queue();
}
方法methodQueue之后在組件初始化時(shí)被調(diào)用一次.
輸出實(shí)例
除了可以輸出方法,還有輸出實(shí)例.
- (NSDictionary *)constantsToExport
{
return @{ @"firstDayOfTheWeek": @"Monday" };
}
在JS端可以直接獲取console.log(CalendarManager.firstDayOfTheWeek);
只有在初始化時(shí)實(shí)例輸出才是有效的,如果在運(yùn)行時(shí)修改constantsToExport是不會(huì)影響JS環(huán)境的數(shù)據(jù)的.
輸出枚舉
通過(guò)typedef NS_ENUM()定義的枚舉,可以通過(guò)增加RCTConvert的擴(kuò)展來(lái)完成
@implementation RCTConvert (StatusBarAnimation)
RCT_ENUM_CONVERTER(UIStatusBarAnimation, (@{ @"statusBarAnimationNone" : @(UIStatusBarAnimationNone),
@"statusBarAnimationFade" : @(UIStatusBarAnimationFade),
@"statusBarAnimationSlide" : @(UIStatusBarAnimationSlide)}),
UIStatusBarAnimationNone, integerValue)
@end
之后就可以通過(guò)輸出屬性和方法等方式在JS中使用了.
native向JS發(fā)方法
想給JS發(fā)方法,可以繼承類(lèi)RCTEventEmitter,實(shí)現(xiàn)supportedEvents方法,然后通過(guò)調(diào)用self sendEventWithName:即可.
RCT_EXPORT_MODULE();
- (NSArray<NSString *> *)supportedEvents
{
return @[@"EventReminder"];
}
- (void)calendarEventReminderReceived:(NSNotification *)notification
{
NSString *eventName = notification.userInfo[@"name"];
[self sendEventWithName:@"EventReminder" body:@{@"name": eventName}];
}
JS端可以通過(guò)NativeEventEmitter進(jìn)行注冊(cè)和調(diào)用
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內(nèi)執(zhí)行.
客戶(hù)端可以通過(guò)一些方式獲取JS注冊(cè)和移除訂閱的事件,來(lái)優(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
}
資料
總結(jié)
以上就是這篇文章的全部?jī)?nèi)容了,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,如果有疑問(wèn)大家可以留言交流,謝謝大家對(duì)腳本之家的支持。
相關(guān)文章
ReactJS?應(yīng)用兼容ios9對(duì)標(biāo)ie11解決方案
這篇文章主要為大家介紹了ReactJS?應(yīng)用兼容ios9對(duì)標(biāo)ie11解決方案詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-01-01
React18之update流程從零實(shí)現(xiàn)詳解
這篇文章主要為大家介紹了React18之update流程從零實(shí)現(xiàn)詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-01-01
Rect Intersection判斷兩個(gè)矩形是否相交
這篇文章主要為大家介紹了Rect Intersection判斷兩個(gè)矩形是否相交的算法詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-06-06
使用React hook實(shí)現(xiàn)remember me功能
相信大家在使用 React 寫(xiě)頁(yè)面的時(shí)候都遇到過(guò)完成 Remember me 的需求吧!本文就將這個(gè)需求封裝在一個(gè) React hook 中以供后續(xù)的使用,覺(jué)得有用的同學(xué)可以收藏起來(lái)以備不時(shí)之需,感興趣的小伙伴跟著小編一起來(lái)看看吧2024-04-04
React Native實(shí)現(xiàn)進(jìn)度條彈框的示例代碼
本篇文章主要介紹了React Native實(shí)現(xiàn)進(jìn)度條彈框的示例代碼,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-07-07
react?+?vite?+?ts項(xiàng)目中優(yōu)雅使用.svg文件
這篇文章主要為大家介紹了react?+?vite?+?ts項(xiàng)目中優(yōu)雅使用.svg文件,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-08-08
React Zustand狀態(tài)管理庫(kù)的使用詳解
Zustand是一個(gè)為React和瀏覽器環(huán)境設(shè)計(jì)的輕量級(jí)狀態(tài)管理庫(kù),由Vercel開(kāi)發(fā),它特點(diǎn)包括輕量級(jí)、易用性、靈活性、可組合性和性能優(yōu)化,支持多種狀態(tài)管理模式和中間件,適合中小型項(xiàng)目,Zustand還支持TypeScript,提供類(lèi)型安全的支持2024-09-09
用react-redux實(shí)現(xiàn)react組件之間數(shù)據(jù)共享的方法
這篇文章主要介紹了用react-redux實(shí)現(xiàn)react組件之間數(shù)據(jù)共享的方法,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2018-06-06

