开发自己的react-native组件并发布到npm[转]
原文链接:https://www.jianshu.com/p/091a68ea1ca7
写在前面
在做react-native
开发的时候,我们经常会找到一些第三方组件,并且通过npm install
的方式很方便的安装使用。在使用的同时,你是否想过,我们自己应该如何开发并发布一个组件呢?不管是给自己的多个项目共用,或者开源给到别人用,这都是一件很酷的事情。
那么今天,我就以我自己开发的一个在ios
和android
通用的CardView
组件为例来讲一下,如何开发一个自己的组件,并开源到github、发布到npm上去
一个说明
我的组件名为react-native-rn-cardview。教程里如果出现react-native-cardview
组件名,视为同一意思。
1 创建并实现
1.1 创建自定义组件模版项目
1.1.1 安装react-native-create-library
$ npm install -g react-native-create-library
1.1.2 创建模板项目
我们用命令react-native-create-library
创建项目,并指定平台为ios,android
,指定android
中的package
,其他参数可以自行参考在react-native-create-library在 github
上的文档说明,这里就不赘述
$ react-native-create-library --package-identifier com.quenice.cardview --platforms android,ios cardview
我们重命名一下项目名
$ mv cardview react-native-cardview
有人可能会说,楼主为什么不直接生成react-native-cardview
的项目,而要先生成cardview
再重命名。其实这是一个小技巧,因为利用react-native-create-library
生产的项目,一些跟组件相关的名称或者类会默认加上react-native
或者RN
前缀。
例如,如果你的初始项目名是react-native-card-view
,那么package.json
中定义的组件名将是react-native-react-native-card-view
,android模块中定义的相关类会是RNReactNativeCardviewModule.java
,这显然比较丑啊。
ok, 我们继续。
现在的目录结构:
$ tree
└── react-native-cardview
├── README.md
├── android
│ ├── build.gradle
│ └── src
│ └── main
│ ├── AndroidManifest.xml
│ └── java
│ └── com
│ └── reactlibrary
│ ├── RNCardviewModule.java
│ └── RNCardviewPackage.java
├── index.js
├── ios
│ ├── RNCardview.h
│ ├── RNCardview.m
│ ├── RNCardview.podspec
│ ├── RNCardview.xcodeproj
│ │ └── project.pbxproj
│ └── RNCardview.xcworkspace
│ └── contents.xcworkspacedata
└── package.json
生成好组件项目后,就可以开始编写实现代码了
2 编写代码
编写代码分为三部分,一部分是android原生代码,一部分是iOS原生代码,一部分是react-native(或者javascript)代码。由于react-native-cardview只涉及到android原生模块,所以本篇文章暂不涉及到iOS原生模块开发,如果大家感兴趣,我可以另开一篇文章专门讲一下iOS原生模块相关内容
2.1 编写Android Native Module
编写android原生代码,一般以下三个类是必须的:
2.1.1 RNxxxModule
这个类主要作用是定义原生模块名,可以直接在javascript中通过React.NativeModules.xxx
来访问,其中xxx
是在RNxxxModule
类中定义的getName
方法返回值。以下为我组件react-native-cardview中的Module类
package com.quenice.reactnative;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactContextBaseJavaModule;
import com.facebook.react.bridge.ReactMethod;
import com.facebook.react.bridge.Callback;
public class RNCardViewModule extends ReactContextBaseJavaModule {
private final ReactApplicationContext reactContext;
public RNCardViewModule(ReactApplicationContext reactContext) {
super(reactContext);
this.reactContext = reactContext;
}
@Override
public String getName() {
return "RNCardView";
}
}
2.1.2 RNxxxManager
Manager类主要是组件的原生实现,并且把react-native组件的属性映射到原生属性
package com.quenice.reactnative;
import android.graphics.Color;
import android.support.v7.widget.CardView;
import android.view.View;
import com.facebook.react.uimanager.PixelUtil;
import com.facebook.react.uimanager.ThemedReactContext;
import com.facebook.react.uimanager.ViewGroupManager;
import com.facebook.react.uimanager.annotations.ReactProp;
import com.facebook.react.views.view.ReactViewGroup;
public class RNCardViewManager extends ViewGroupManager<CardView> {
@Override
public String getName() {
return "RNCardView";
}
@Override
protected CardView createViewInstance(ThemedReactContext reactContext) {
CardView cardView = new CardView(reactContext);
cardView.setUseCompatPadding(true);
cardView.setContentPadding(0, 0, 0, 0);
ReactViewGroup reactViewGroup = new ReactViewGroup(reactContext);
cardView.addView(reactViewGroup);
return cardView;
}
@ReactProp(name = "cardElevation", defaultFloat = 0f)
public void setCardElevation(CardView view, float cardElevation) {
view.setCardElevation(PixelUtil.toPixelFromDIP(cardElevation));
}
...
}
2.1.3 RNxxxPackage
Package类主要用于注册原生模块、原生组件实现,也就是注册上面的Module和Manager类
package com.quenice.reactnative;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import com.facebook.react.ReactPackage;
import com.facebook.react.bridge.NativeModule;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.uimanager.ViewManager;
import com.facebook.react.bridge.JavaScriptModule;
public class RNCardViewPackage implements ReactPackage {
@Override
public List<NativeModule> createNativeModules(ReactApplicationContext reactContext) {
return Arrays.<NativeModule>asList(new RNCardViewModule(reactContext));
}
// Deprecated from RN 0.47
public List<Class<? extends JavaScriptModule>> createJSModules() {
return Collections.emptyList();
}
@Override
public List<ViewManager> createViewManagers(ReactApplicationContext reactContext) {
return Arrays.<ViewManager>asList(new RNCardViewManager());
}
}
2.2 编写iOS原生代码
react-native-cardview
iOS
的实现方式直接利用react-native
中shadow
相关属性就可以实现,所以本文暂不涉及
2.3 编写ReactNative代码
编写好了android/iOS
原生模块后,需要编写javascript
代码来桥接react-native
与原生模块。
import PropTypes from 'prop-types';
import {requireNativeComponent, View} from 'react-native';
const iface = {
name: 'CardView',
propTypes: {
cardElevation: PropTypes.number,
maxCardElevation: PropTypes.number,
backgroundColor: PropTypes.string,
radius: PropTypes.number,
...View.propTypes, // include the default view properties
},
};
module.exports = requireNativeComponent('RNCardView', iface);
3 代码上传与组件发布
3.1 代码上传到github
编写完代码后,我们需要把它上传到github上,之后在组件发布到npm的时候也需要用到代码的github地址
。如果你没有做github相关的配置,可以参考我另一篇文章:安装GIt并配置连接GitHub
执行以下命令把代码同步到你github对应的repository中:
$ git add .
$ git commit -a -m "initial commit"
$ git push -u origin master
同步之后可以到github中看下是否push成功:
https://github.com/YourGithubAccount/YourRepository
3.2 组件发布
开发好组件之后,想在其他的项目(或者提供给其他人安装使用)中通过npm install
的方式安装你的组件,那么你的组件必须发布到npm registry中。
3.2.1 npm registry
npm registry 是什么
简单来说,npm registry就相当于一个包注册管理中心。它管理着全世界的开发者们发布上来的各种插件,同时开发者们可以通过npm install
的方式安装所需要的插件。
npm官方registry为:http://registry.npmjs.org/
国内速度较快的为:https://registry.npm.taobao.org/
查看
你可以查看当前使用的registry:
$ npm config get registry
切换
当然也可以通过命令切换当前使用的npm registry
# 全局切换
$ npm config set registry http://registry.npmjs.org/
有时候你可能只想在执行某些npm命令时临时切换,这个时候,可以使用--registry
来指定临时切换的registry,比如在npm发布
$ npm publish --registry http://registry.npmjs.org/
就可以临时指定,当然,在命令执行结束之后,registry仍然会恢复到原来的registry
3.2.2 创建/登陆npm registry账户
要发布组件到npm registry,你必须要是npm registry的注册用户,通过:
$ npm adduser
来新增一个用户,或者你已经在官网注册了一个用户,可以通过:
$ npm login
来登陆npm registry账户。
利用以下两种方式来确认你是否创建/登陆成功npm registry
- 命令
$ npm whoami
确认本地是否成功登陆认证成功 - 在线打开 https://npmjs.com/~username 查看是否创建账户成功
3.2.3 发布前准备
3.2.3.1 .gitignore 和 .npmignore
- 在.gitignore中定义哪些文件不上传到github中
- 在.npmignore中定义哪些文件发布时不打包
- 如果有.gitignore但是没有.npmignore文件,那么.gitignore可以充当.npmignore的作用
- 具体规则可以参照:npm-developers, .gitignore or .npmignore pattern rules
3.2.3.2 package.json
package.json文件定义了发布的所有信息,包括:组件名、版本、作者、描述、依赖等等关键信息。具体可以参照 Working with package.json
下面是react-native-cardview的package.json文件内容:
{
"name": "react-native-rn-cardview",
"version": "1.0.0",
"description": "A ReactNative CardView Component for android and iOS",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [
"react-native",
"react-component",
"react-native-component",
"react",
"mobile",
"ios",
"android",
"cardview"
],
"author": {
"name": "quenice",
"email": "qiubing.it@gmail.com"
},
"license": "MIT",
"repository": {
"type": "git",
"url": "git@github.com:quenice/react-native-cardview.git"
},
"devDependencies": {
"react": "^16.2.0",
"react-native": "^0.53.0"
},
"peerDependencies": {
"react": "^16.2.0"
},
"dependencies": {
"prop-types": "^15.6.0"
}
}
3.2.3.3 编写readme.md
可以在readme.md文件中详细说明组件的使用方法、注意事项等。一般使用Markdown语法来编写
3.2.4 发布
做好以上准备之后,就可以发布了。这里需要注意,首次发布跟后面更新发布是不一样的。
首次发布
第一次发布的话,直接执行命令:
$ npm publish
就搞定了,可以在线查看确认是否发布成功。访问链接(<package>是你发布的npm package名):
https://www.npmjs.com/package/<package>
看看是否已经有内容了,有内容说明发布成功了。
更新发布
如果不是首次发布,需要执行两个命令
$ npm version <update_type>
$ npm publish
$ npm version
命令是用来自动更新版本号,update_type
取值有patch
minor
major
。那么在什么场景应该选择什么update_type
呢?看下表
update_type | 场景 | 版本号规则 | 举例 |
---|---|---|---|
- | 首次发布 | 版本号1.0.0 | 1.0.0 |
patch | 修复bug、微小改动时 | 从版本号第3位开始增量变动 | 1.0.0 -> 1.0.1 |
minor | 上线新功能,并且对当前版本已有功能模块不影响时 | 从版本号第2位开始增量变动 | 1.0.3 -> 1.1.3 |
major | 上线多个新功能模块,并且对当前版本已有功能会有影响时 | 从版本号第1位开始增量变动 | 1.0.3 -> 2.0.0 |
注意
如果首次发布版本号不是1.0.0的话,那么用$ npm version <update_type>
来更新会报错,因为你没有按照它约定的版本规则来,这个时候,你可以手动修改package.json
中的version
字段为符合约定规则的版本号,然后直接执行$ npm publish
就可以,然后下次再增量更新的时候,就可以直接使用$ npm version <update_type>
的方式来自动更新版本号了
4 测试
组件从开发到最终发布的过程中,需要不断进行测试,确保功能正常,那如何进行测试呢?
4.1 创建一个react-native项目
首先我们创建一个叫做example的react-native项目
$ react-native init example
example
项目目录可以和组件项目目录react-native-cardview
同级,当然你也可以放在任何你想放的位置,这里为了操作方便,我们就把两个目录放在同级目录。也就是说,现在的目录是这样
$ tree
.
├── example
└── react-native-cardview
然后我们要做的就是把本地或者已发布的组件安装到example
项目中进行测试
4.2 本地代码测试
在组件未发布之前,我们可以直接安装本地代码到example
项目中进行测试,有以下几种方式都可以做到
4.2.1 yarn link
$ cd react-native-cardview
$ yarn link
$ cd ../example
$ yarn link react-native-cardview
$ react-native link react-native-cardview
说明几点:
yarn link
是把当前目录中的本地代码用yarn注册为react-native-cardview
的一个本地组件,组件名字react-native-cardview
其实是根据package.json
中的name
字段的值来的,跟目录名无关,只不过这里正好等于目录名yarn link react-native-cardview
命令是把这个本地组件react-native-cardview
安装到了example
的项目中,你可以在example/node_modules
中找到这个组件react-native link react-native-cardview
这个大家应该知道,就是做了android/iOS
的原生模块link- 其实
yarn link
这种方式简单来说,就是做了一个symbol link
,也就是说,example/node_modules/react-native-cardview/
目录中的内容是指向react-native-cardview/
目录内容,你改动react-native-cardview/
目录下的代码,相当于直接改动example/node_modules/react-native-cardview/
这个目录中的代码,这样就能够达到边修改组件代码边看效果的目的了
4.2.2 package.json中配置本地路径
直接在example
的package.json
中增加dependencies
example/package.json
{
"name":"example",
...
"dependencies": {
"react-native": "^0.55.4",
"react-native-cardview":"file:../react-native-cardview",
...
}
...
}
然后执行
$ react-native link react-native-cardview
跟yarn link
一样,也相当于做了symbol link
,直接修改react-native-cardview/
目录下的代码,相当于直接改动example/node_modules/react-native-cardview/
这个目录中的代码
4.2.3 直接copy本地代码
这种方式就比较简单粗暴了,直接copyreact-native-cardview/
目录中内容到example/node_modules/react-native-cardview/
这个目录中
$ cp -rf react-native-cardview/ example/node_modules/
然后执行
$ react-native link react-native-cardview
这种方式缺点就是每次在react-native-cardview/
改完代码后,需要手工copy到example/node_modules/react-native-cardview/
4.3 已上传/发布代码测试
已上传到github或者发布到npm registry的组件,测试方式就跟普通我们安装一个第三方组件一样了。
4.3.1 通过github
加入你的代码通过git上传到了github仓库上,那么,你可以直接通过npm install
来安装你的组件
npm install --save https://github.com/quenice/react-native-cardview.git
或者
npm install --save git@github.com:quenice/react-native-cardview.git
注意:根据你自己ghthub上的URL替换以上的HTTPS
或者SSH
然后执行
$ react-native link react-native-rn-cardview
4.3.2 通过npm
这种方式就跟按照第三方组件没有区别了
$ npm install --save react-native-rn-cardview
然后执行
$ react-native link react-native-rn-cardview
结语
至此,一个react-native
组件完整的开发-测试-发布的生命周期就讲完了。
由于是结合我自己开发的组件react-native-rn-cardview的实际开发过程,所以难免有遗漏,肯定也有许多不足的地方。如果大家有什么问题,或者发现哪里有错误,欢迎大家在评论区给我留言,我们一起探讨、一起解决。
另外如果在react-native
中有需要用到CardView
的,欢迎使用react-native-rn-cardview
开发自己的react-native组件并发布到npm[转]的更多相关文章
- Android React Native组件的生命周期及回调函数
熟悉android的童鞋应该都清楚,android是有生命周期的,其很多组件也是有生命周期.今天小编和大家分享的React Native组件的生命周期,还不了解的童鞋,赶紧来围观吧 在android开 ...
- React Native v0.4 发布,用 React 编写移动应用
React Native v0.4 发布,自从 React Native 开源以来,包括超过 12.5k stars,1000 commits,500 issues,380 pull requests ...
- beeshell —— 开源的 React Native 组件库
介绍 beeshell 是一个 React Native 应用的基础组件库,基于 0.53.3 版本,提供一整套开箱即用的高质量组件,包含 JavaScript(以下简称 JS)组件和复合组件(包含 ...
- React Native组件(三)Text组件解析
相关文章 React Native探索系列 React Native组件系列 前言 此前介绍了最基本的View组件,接下来就是最常用的Text组件,对于Text组件的一些常用属性,这篇文章会给出简单的 ...
- React Native组件(二)View组件解析
相关文章 React Native探索系列 React Native组件系列 前言 了解了RN的组件的生命周期后,我们接着来学习RN的具体的组件.View组件是最基本的组件,也是首先要掌握的组件,这一 ...
- React Native组件的结构和生命周期
React Native组件的结构和生命周期 一.组件的结构 1.导入引用 可以理解为C++编程中的头文件. 导入引用包括导入react native定义的组件.API,以及自定义的组件. 1.1 导 ...
- React Native组件间通信
React Native组件间通信 React Native组件的关系有:父子关系.无直接关系.组件间通信主要针对这两类来讨论. 一.父组件和子组件之间通信 父组件向子组件传递消息.数据通过对子组件的 ...
- 如何创建一个前端 React 组件并发布到 NPM
首先npm文档摆在这里: https://www.npmjs.cn/ 参考组件 https://github.com/rakuten-rex/rex-dropdownhttps://www.npmjs ...
- React Native组件之Text
React Native组件之Text相当于iOS中的UILabel. 其基本属性如下: /** * Sample React Native App * https://github.com/face ...
随机推荐
- numba学习教程
一.对于python的基础介绍 Python是一种高效的动态编程语言,广泛用于科学,工程和数据分析应用程序..影响python普及的因素有很多,包括干净,富有表现力的语法和标准数据结构,全面的“电池包 ...
- python11 函数的定义,调用,分类
## 复习 #一.什么是函数:具体特定功能的代码块 - 特定功能代码块作为一个整体,并给该整体命名,就是函数 # 二.函数的优点:# 1.减少代码的冗余# 2.结构清晰,可读性强# 3.具有复用性,开 ...
- python模拟蒙特·卡罗法计算圆周率
蒙特·卡罗方法是一种通过概率来得到问题近似解的方法,在很多领域都有重要的应用,其中就包括圆周率近似值的计问题. 假设有一块边长为2的正方形木板,上面画一个单位圆,然后随意往木板上扔飞镖,落点坐标(x, ...
- Tomcat系列(7)——Tomcat类加载机制
1. 核心部分 1. 类加载器: 通过一个类的全限定名来获取描述此类的二进制字节流. 对于任意一个类,都需要由加载他的类加载器和这个类本身一同确立其在Java虚拟机中的唯一性,每一个类加载器,都拥有一 ...
- Nuxt.js笔记
前置知识 SSR服务器渲染 Vue SSR(server side rendering)服务端渲染 和 Vue SPA(single page application)单页应用 Vue SSR-> ...
- Android AVD启动报错: This AVD's configuration is missing a kernel file! Please ensure the file "kernel-qemu" is in the same location as your system image.
启动Android SDK manager重新下载安装
- IMDB-二分类问题
from keras.datasets import imdb from keras.utils.np_utils import to_categorical import numpy as np f ...
- OSG开源教程(转)
例:geom->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::QUADS,0,4)); 来指定要利用这些数据生成一个怎么样的形状. ...
- VGA、DVI、HDMI三种视频信号接口
目前,电脑显示器常见的接口主要有HDMI.DP.DVI.VGA等4种接口.显示器数据线性能排名:DP>HDMI>DVI>VGA.其中 VGA是模拟信号,已经被主流所淘汰,DVI.H ...
- Discuz x 转码要记
Discuz 开源项目仅保留了 UTF8 编码版本,要从GBK版本升级,须进行编码转换. 转换主要执行以下步骤: 关闭网站,做好源文件备份: 导出数据库,在MySQL中生成Self-Contained ...