ReactNative: 将自定义的ReactNative组件制作成第三方库的详细流程(制作-->发布)
一、简介
在讲本篇博文之前,需要你熟知怎么自定义ReactNative组件,然后才好学习将自定义的ReactNative组件制作成第三方库。本文中的自定义的ReactNative组件LoginManager API 源自上篇文章,所以需要先看一下上篇博文。言归正传,ReactNative的确提供了一个非常便捷的方式来扩展Native模块。如果要把模块做成第三方组件的话,还有一些工作要做:首先以一个静态库工程来编译模块代码,提供JavaScript的封装,最后创建Package.json来支持node的引用。在步骤开始之前,我先把上篇文章中创建Native原生模块的LoginManager API组件的类贴出来,如下所示:
LoginManager.h
//
// LoginManager.h
// RNDemo
//
// Created by 夏远全 on 2020/1/16.
// Copyright © 2020 Facebook. All rights reserved.
// #import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
#import <React/RCTUtils.h>
#import <React/RCTEventDispatcher.h>
#import <React/RCTBridgeModule.h> NS_ASSUME_NONNULL_BEGIN //OC中定义一个枚举并导出
typedef NS_ENUM(NSInteger, MoveDiretion){
MoveDiretionNone,
MoveDiretionLeft,
MoveDiretionRight,
MoveDiretionBottom,
MoveDiretionTop
}; @interface LoginManager : NSObject<RCTBridgeModule> @end NS_ASSUME_NONNULL_END
LoginManager.m
//
// LoginManager.m
// RNDemo
//
// Created by 夏远全 on 2020/1/16.
// Copyright © 2020 Facebook. All rights reserved.
// #import "LoginManager.h" #ifdef DEBUG
#define NSLog(format, ...) printf("[%s] %s [第%d行] %s\n", __TIME__, __FUNCTION__, __LINE__, [[NSString stringWithFormat:format, ## __VA_ARGS__] UTF8String]);
#else
#define NSLog(format, ...)
#endif @implementation LoginManager //初始化, 添加屏幕旋转监听者
-(instancetype)init {
self = [super init];
if (self) {
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(orientationDidChange:) name:UIDeviceOrientationDidChangeNotification object:nil];
}
return self;
} //导出模块类
RCT_EXPORT_MODULE(); //重映射,auth为code方法的新名称
RCT_REMAP_METHOD(auth,code:(NSString *)account{
NSLog(@"%s---获取验证----",__func__);
NSLog(@"account----%@",account);
}); //login为方法名
RCT_EXPORT_METHOD(login:(NSString *)account password:(NSString *)password{
NSLog(@"%s---登录账号----",__func__);
NSLog(@"account----%@",account);
NSLog(@"password----%@",password);
}); //logout为方法名
RCT_EXPORT_METHOD(logout:(NSString *)account{
NSLog(@"%s---退出账号----",__func__);
NSLog(@"account----%@",account);
}); //设置普通的回调函数
//fetchUserInfoWithToken为方法名,successCallback为成功回调,failureCallback为失败回调
RCT_EXPORT_METHOD(fetchUserInfoWithToken:(NSString *)token success:(RCTResponseSenderBlock)successCallback failure:(RCTResponseErrorBlock)failureCallback
{
if(token.length> && successCallback){
successCallback(@[
@"account = xiayuanquan",
@"password = 123456",
[NSString stringWithFormat:@"token = %@",token]
]);
}
else{
if(failureCallback){
failureCallback(
[[NSError alloc] initWithDomain:NSOSStatusErrorDomain
code:
userInfo: @{NSLocalizedDescriptionKey: @"token exception"}]
);
}
}
}); //设置异步处理的回调函数
//sendMessage为方法名,successCallback为成功回调,failureCallback为失败回调
RCT_EXPORT_METHOD(sendMessage:(NSString *)message success:(RCTPromiseResolveBlock)successCallback failure:(RCTPromiseRejectBlock)failureCallback
{
if(message.length> && successCallback){
successCallback(@"发送成功!");
}
else{
if(failureCallback){
failureCallback(@"",@"发送失败",nil);
}
}
}); //重写constantsToExport, 枚举常量导出
- (NSDictionary<NSString *, id> *)constantsToExport {
return @{
@"MoveDiretionNone": @(MoveDiretionNone),
@"MoveDiretionLeft": @(MoveDiretionLeft),
@"MoveDiretionRight": @(MoveDiretionRight),
@"MoveDiretionBottom": @(MoveDiretionBottom),
@"MoveDiretionTop": @(MoveDiretionTop)
};
} //定义一个移动方法,根据传入的枚举值移动
//move为方法名
RCT_EXPORT_METHOD(move:(MoveDiretion)moveDiretion{
switch(moveDiretion){
case MoveDiretionNone:
NSLog(@"仍保持原始位置 --- MoveDiretionNome");
break;
case MoveDiretionLeft:
NSLog(@"向左边移动位置 --- MoveDiretionLeft");
break;
case MoveDiretionRight:
NSLog(@"向右边移动位置 --- MoveDiretionRight");
break;
case MoveDiretionBottom:
NSLog(@"向下边移动位置 --- MoveDiretionBottom");
break;
case MoveDiretionTop:
NSLog(@"向上边移动位置 --- MoveDiretionTop");
break;
}
}); //可以重写队列,给当前模块类指定自定义的串行队列。若不指定,则系统默认会给当前模块类随机分配一个串行队列。
//这个方法一旦重写。当前模块的所有方法均会在该自定义的串行队列中异步执行
-(dispatch_queue_t)methodQueue{
return dispatch_queue_create("com.facebook.ReactNative.LoginManagerQueue", DISPATCH_QUEUE_SERIAL);
} //定义一个方法,获取线程和队列信息
//thread为方法名
RCT_EXPORT_METHOD(thread:(BOOL)newQueue{ const char *queueName = dispatch_queue_get_label([self methodQueue]);
NSLog(@"当前线程1 ------- %@-----%s", [NSThread currentThread], queueName); if(newQueue){ dispatch_async(dispatch_get_main_queue(), ^{
const char *queueName2 = dispatch_queue_get_label(dispatch_get_main_queue());
NSLog(@"当前线程2 ------- %@ -------%s", [NSThread currentThread], queueName2);
}); dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, ), ^{
const char *queueName3 = dispatch_queue_get_label(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, ));
NSLog(@"当前线程3 ------- %@-------%s", [NSThread currentThread], queueName3);
});
}
}); //获取当前屏幕的尺寸
static NSDictionary *Dimensions(){
CGFloat width = MIN(RCTScreenSize().width, RCTScreenSize().height);
CGFloat height = MAX(RCTScreenSize().width, RCTScreenSize().height);
CGFloat scale = RCTScreenScale();
if(UIDeviceOrientationIsLandscape([UIDevice currentDevice].orientation)){
width = MAX(RCTScreenSize().width, RCTScreenSize().height);
height = MIN(RCTScreenSize().width, RCTScreenSize().height);
}
return @{
@"width": @(width),
@"height": @(height),
@"scale": @(scale)
};
}
//定义一个方法,获取屏幕信息
//getDimensions为方法名
RCT_EXPORT_METHOD(getDimensions:(RCTResponseSenderBlock)callback{
if (callback) {
callback(@[[NSNull null], Dimensions()]);
}
}); //监听方法,使用RCTEventDispatcher的eventDispatcher调用sendDeviceEventWithName函数发送事件信息
//可以将事件名称作为常量导出,提供给ReactNative中使用,也即添加到constantsToExport方法中的字典中即可。类似上面的枚举。
@synthesize bridge = _bridge;
-(void)orientationDidChange:(NSNotification *)notification {
[_bridge.eventDispatcher sendDeviceEventWithName:@"orientationDidChange" body:@{
@"orientation": UIDeviceOrientationIsLandscape([UIDevice currentDevice].orientation) ? @"Landscape": @"Portrait",
@"Dimensions": Dimensions()}
];
} //移除监听者
-(void)dealloc{
[[NSNotificationCenter defaultCenter] removeObserver:self];
} @end
RCTConvert+MoveDiretion.h
//
// RCTConvert+MoveDiretion.h
// RNDemo
//
// Created by 夏远全 on 2020/1/17.
// Copyright © 2020 Facebook. All rights reserved.
// #import <React/RCTConvert.h> NS_ASSUME_NONNULL_BEGIN @interface RCTConvert (MoveDiretion) @end NS_ASSUME_NONNULL_END
RCTConvert+MoveDiretion.m
//
// RCTConvert+MoveDiretion.m
// RNDemo
//
// Created by 夏远全 on 2020/1/17.
// Copyright © 2020 Facebook. All rights reserved.
// #import "RCTConvert+MoveDiretion.h"
#import "LoginManager.h" @implementation RCTConvert (MoveDiretion) //给RCTConvert类添加扩展,这样在模块方法调用中使用常量导出的枚举值,通信到Native中时,会从整型自动转换为定义的枚举类型
RCT_ENUM_CONVERTER(MoveDiretion,(@{
@"MoveDiretionNone": @(MoveDiretionNone),
@"MoveDiretionLeft": @(MoveDiretionLeft),
@"MoveDiretionRight": @(MoveDiretionRight),
@"MoveDiretionBottom": @(MoveDiretionBottom),
@"MoveDiretionTop": @(MoveDiretionTop),
}), MoveDiretionNone, integerValue) @end
二、步骤
1、使用xcode创建一个名为LoginManager的静态库。
2、打开静态库,将上面贴出来的已经实现好了的Native模块LoginManager API组件的类全部拷贝进去或进行替换。
3、选择Build Settings,配置Header Search Paths路径。
6、打开终端,初始化一个新的RN项目,随意设置一个名称为:LoginManagerTestProject。(本人安装的ReactNative版本较低)
//初始化
react-native init LoginManagerTestProject --version 0.44.
7、进入目录node_modules。
//进入node_modules
cd LoginManagerTestProject/node_modules
8、创建要制作的第三库文件夹,指定名称为:react-native-login-manager。
//创建第三方名称
mkdir react-native-login-manager
9、进入这个第三方库文件夹。
//进入库文件
cd react-native-login-manager
10、创建ios文件夹。
//创建ios文件
mkdir ios
11、将之前创建的静态库中的根目录下的文件全部copy到这个RN工程LoginManagerTestProject/node_modules/react-native-login-manager/ios目录下。目录结构如下:
12、使用xcode打开这个RN工程LoginManagerTestProject,将静态库LoginManager的.xcodeproj文件 拖到 RN工程LoginManagerTestProject的Libraries文件下。
13、手动添加libLoginManager.a静态包,然后编译,如果编译不出错,则success。
14、使用终端或者webStorm等编程工具进入到RN工程LoginManagerTestProject/node_modules/react-native-login-manager目录下,创建index.js文件,它是整个原生模块的入口,我们这里只是将原生LoginManager模块类进行导出。此时也就完成了第三方库制作的第一步了,仅仅可以自己使用。 (还需要发布到npm上,分享给大家安装使用)
三、测试
好了,咱先自己测试一下,看看行不行。结果是行的,
ReactNative: 将自定义的ReactNative组件制作成第三方库的详细流程(制作-->发布)的更多相关文章
- vue 移动端轻量日期组件不依赖第三方库
Vue版移动端日期选择组件 1.优点:不需要依赖其他第三方库,灵活可配置: 不需要依赖第三方组件的vue日期移动端组件 小轮子 轻量可复用: https://github.com/BeckReed ...
- Qt动态库静态库的创建、使用、多级库依赖、动态库改成静态库等详细说明
本文描述的是windows系统下,通过qtcreator在pro文件中添加动态库与静态库的方法: 1.添加动态库(直接添加动态库文件.dll,非子项目) 通过qtcreator创建动态库的方法就不在此 ...
- ReactNative: 创建自定义List列表组件
一.介绍 在App中,很多数据消息显示都是一行行动态展示的,例如新闻标题,其实每一条新闻标题都可以独立成一个简单的列表组件,之前我们使用Text组件将数据都写死了,为了提高组件的灵活性,我们可以使用T ...
- Egret第三方库的制作和使用(模块化 第三方库)
一.第三方库的制作 官方教程:第三方库的使用方法 水友帖子:新版本第三方库制作细节5.1.x 首先在任意需要创建第三方库的地方,右键,选择"在此处打开命令窗口" 输入egret c ...
- Egret的第三方库制作,以及在大型项目中的应用
目录: 一 创建第三方库 二 TypeScript库 三 JavaScript库 四 第三方库制作在大型RPG中的实际应用 参考: 第三方库的使用方法 目标: 本文目的是将现有游戏的框架制作成第三方库 ...
- ReactNative Android之原生UI组件动态addView不显示问题解决
ReactNative Android之原生UI组件动态addView不显示问题解决 版权声明:本文为博主原创文章,未经博主允许不得转载. 转载请表明出处:http://www.cnblogs.com ...
- React Native实战系列教程之自定义原生UI组件和VideoView视频播放器开发
React Native实战系列教程之自定义原生UI组件和VideoView视频播放器开发 2016/09/23 | React Native技术文章 | Sky丶清| 4 条评论 | 1 ...
- react-native技术调研:react-native是什么?
如有疏漏错误,还望指正.转载不忘加上>>原链接<<哦~ react-native是什么? react-native原理 从字面意思上来看,react-native由单词reac ...
- iOS开发之自定义表情键盘(组件封装与自动布局)
下面的东西是编写自定义的表情键盘,话不多说,开门见山吧!下面主要用到的知识有MVC, iOS开发中的自动布局,自定义组件的封装与使用,Block回调,CoreData的使用.有的小伙伴可能会问写一个自 ...
随机推荐
- Vue自定义指令配置修饰符和传参
一和二,请参考https://www.cnblogs.com/zui-ai-java/p/11109213.html 三.index.html <!DOCTYPE html> <ht ...
- 4-2 setting中一定要将ROBOTSTXT_OBEY = False的注释去掉
# Obey robots.txt rules##默认遵循robots协议的,默认去读取每个网站上的robots协议ROBOTSTXT_OBEY = False
- Mac下SVN基本操作和常见错误
一.基本操作 1 从服务器上下载代码 svn checkout http://xxx.xxx.xxx/xxx 2 获取最新的代码 svn update 3 提交代码 svn commit -m ...
- python面向对象之三大特性
继承 先看个简单的例子了解一下继承. class Animal: # 父类 def __init__(self, name, age, department): self.name = name se ...
- MySQL视图 definer & invoker 权限
1.创建视图 CREATE VIEW `NewView`AS SELECT `user`.USER_ID, `user`.USER_NAME, department.DEPT_ID, departme ...
- H3C 三种生成树协议特性的比较
- 一排盒子,jq鼠标移入的盒子动画移出停止动画,css动画
css .category > div.active { animation: servicetobig 0.5s ease 1 forwards; } @keyframes serviceto ...
- dotnet core 发布只带必要的依赖文件
在使用 dotnet core 发布独立项目的时候,会带上大量依赖的库,但是通过微软提供的工具可以去掉一些在代码没有用到的库. 本文介绍的工具是 Microsoft.Packaging.Tools.T ...
- CITRIX ADC配置SSL卸载
如上图,将ssl的加密解密放在前端的负载均衡设备上,客户端到VPX的访问都是加密的,VPX到后端的服务器都是http的 Step1:上传证书到VPX,如下图: Step2:创建SSL的虚拟服务器并且绑 ...
- 【一起学源码-微服务】Nexflix Eureka 源码六:在眼花缭乱的代码中,EurekaClient是如何注册的?
前言 上一讲已经讲解了EurekaClient的启动流程,到了这里已经有6篇Eureka源码分析的文章了,看了下之前的文章,感觉代码成分太多,会影响阅读,后面会只截取主要的代码,加上注释讲解. 这一讲 ...