React Native自定义组件与输出方法详解

 更新时间:2018年07月06日 15:35:04   作者:sea_biscute  
这篇文章主要给大家介绍了关于React Native自定义组件与输出方法的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

简介

如果你看的这一篇,需要你对ReactNative的开发有一定的了解,此文讲的是在ReactNative提供的组件不能满足需求,或者native用于较成熟的组件想要输出,那么就需要用到自定义组件了.

通过该文,我们也可以对native和JS交互方式进行初步了解,关于输出方法内部实现,我们下一篇再剖.

Native module

native module就是实现了RCTBridgeModule协议的OC类.RCT就是ReaCT的缩写.

具体步骤如下

  • 引入#import <React/RCTBridgeModule.h>类,然后遵守RCTBridgeModule协议.
  • 实现RCT_EXPORT_MODULE(customName)方法. customName是自定义的组件名,如果不填默认为当前类名.这个组件名是用于向JS输出.

输出组建后,默认不会向JS输出任何方法,想要输出方法,需要自定义实现方法输出,使用宏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已经暴露了多个冒号之前同名的方法,RN提供了RCT_REMAP_METHOD ()来制定方法名.

另外一点, RCT_EXPORT_METHOD回调进入的方法,默认并不在主线程,如果想要进行主线程的方法调用,需要手动进行dispatch_async(dispatch_get_main_queue(), ^{});回到主线程

RCT_EXPORT_METHOD参数

RCT_EXPORT_METHOD支持如下的参数类型

  • 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支持的类型.

回调

native module支持回调类型RCTResponseSenderBlock

RCT_EXPORT_METHOD(findEvents:(RCTResponseSenderBlock)callback)
{
 NSArray *events = ...
 callback(@[[NSNull null], events]);
}

RCTResponseSenderBlock只支持一个参数:一个包含了多个参数的数组.在JS端可以如下,默认第一个参数是error.当没有错误时error为空.

CalendarManager.findEvents((error, events) => {
 if (error) {
 console.error(error);
 } else {
 this.setState({events: events});
 }
});

native module只能调用一次回调.如果想传递错误,通过RCTUtils.h类中的RCTMakeError来创建.

Promise

Promise是用于实现异步操作async/await的工具类.如果最后一个参数类型为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执行native module是在一个单独的线程实现的,可以通过- (dispatch_queue_t)methodQueue来控制.如果返回主线程,所有执行的方法会在主线程被执行.

- (dispatch_queue_t)methodQueue
{
 return dispatch_get_main_queue();
}

方法methodQueue之后在组件初始化时被调用一次.

输出实例

除了可以输出方法,还有输出实例.

- (NSDictionary *)constantsToExport
{
 return @{ @"firstDayOfTheWeek": @"Monday" };
}

在JS端可以直接获取console.log(CalendarManager.firstDayOfTheWeek);

只有在初始化时实例输出才是有效的,如果在运行时修改constantsToExport是不会影响JS环境的数据的.

输出枚举

通过typedef NS_ENUM()定义的枚举,可以通过增加RCTConvert的扩展来完成

@implementation RCTConvert (StatusBarAnimation)
 RCT_ENUM_CONVERTER(UIStatusBarAnimation, (@{ @"statusBarAnimationNone" : @(UIStatusBarAnimationNone),
            @"statusBarAnimationFade" : @(UIStatusBarAnimationFade),
            @"statusBarAnimationSlide" : @(UIStatusBarAnimationSlide)}),
      UIStatusBarAnimationNone, integerValue)
@end

之后就可以通过输出属性和方法等方式在JS中使用了.

native向JS发方法

想给JS发方法,可以继承类RCTEventEmitter,实现supportedEvents方法,然后通过调用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端可以通过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内执行.

客户端可以通过一些方式获取JS注册和移除订阅的事件,来优化只在有订阅者的情况下才发送事件.

// 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官文

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对脚本之家的支持。

相关文章

  • ReactJS 应用兼容ios9对标ie11解决方案

    ReactJS 应用兼容ios9对标ie11解决方案

    这篇文章主要为大家介绍了ReactJS 应用兼容ios9对标ie11解决方案详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-01-01
  • React组件通信实现方式详解

    React组件通信实现方式详解

    这篇文章主要介绍了React组件通信,在开发中组件通信是React中的一个重要的知识点,本文通过实例代码给大家讲解react中常用的父子、跨组件通信的方法,需要的朋友可以参考下
    2023-03-03
  • React18之update流程从零实现详解

    React18之update流程从零实现详解

    这篇文章主要为大家介绍了React18之update流程从零实现详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-01-01
  • Rect Intersection判断两个矩形是否相交

    Rect Intersection判断两个矩形是否相交

    这篇文章主要为大家介绍了Rect Intersection判断两个矩形是否相交的算法详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-06-06
  • 使用React hook实现remember me功能

    使用React hook实现remember me功能

    相信大家在使用 React 写页面的时候都遇到过完成 Remember me 的需求吧!本文就将这个需求封装在一个 React hook 中以供后续的使用,觉得有用的同学可以收藏起来以备不时之需,感兴趣的小伙伴跟着小编一起来看看吧
    2024-04-04
  • React Native实现进度条弹框的示例代码

    React Native实现进度条弹框的示例代码

    本篇文章主要介绍了React Native实现进度条弹框的示例代码,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-07-07
  • react + vite + ts项目中优雅使用.svg文件

    react + vite + ts项目中优雅使用.svg文件

    这篇文章主要为大家介绍了react + vite + ts项目中优雅使用.svg文件,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-08-08
  • React Zustand状态管理库的使用详解

    React Zustand状态管理库的使用详解

    Zustand是一个为React和浏览器环境设计的轻量级状态管理库,由Vercel开发,它特点包括轻量级、易用性、灵活性、可组合性和性能优化,支持多种状态管理模式和中间件,适合中小型项目,Zustand还支持TypeScript,提供类型安全的支持
    2024-09-09
  • 详解如何在react中搭建d3力导向图

    详解如何在react中搭建d3力导向图

    本篇文章主要介绍了如何在react中搭建d3力导向图,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2018-01-01
  • 用react-redux实现react组件之间数据共享的方法

    用react-redux实现react组件之间数据共享的方法

    这篇文章主要介绍了用react-redux实现react组件之间数据共享的方法,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2018-06-06

最新评论